Как я могу фильтровать с лучшей производительностью? (ДЖАВА) - PullRequest
1 голос
/ 18 января 2010

Я работаю в небольшом офисе, у меня есть приложение, оно генерирует большой текстовый файл с 14000 строк;

после каждого генерирования я должен фильтровать его, и это действительно скучно;

Я хочу написать приложение с помощью Java, пока не смогу обработать его как можно скорее.

Пожалуйста, помогите мне;Я написал приложение со сканером (конечно, с помощью :)), но это не хорошо, потому что это было очень медленно;

Например, это мой файл:

SET CELL:NAME=CELL:0,CELLID=3;
SET LSCID:NAME=LSC:0,NETITYPE=MDCS,T32=5,EACT=FILTER-NOFILTER-MINR-FILTER-NOFILTER,ENSUP=GV2&NCR,MINCELL=6,MSV=PFR,OVLHR=9500,OTHR=80,BVLH=TRUE,CELLID=3,BTLH=TRUE,MSLH=TRUE,EIHO=DISABLED,ENCHO=ENABLED,NARD=NAP_STLP,AMH=ENABLED(3)-ENABLED(6)-ENABLED(9)

, и я хочу этот вывод(фильтр:)

CELLID :  3
ENSUP  :  GV2&NCR
ENCHO  :  ENABLED
MSLH   :  TRUE
------------------------
Count of CELLID : 2

какое решение лучше и быстрее, чем другое?

это мой исходный код:

public static void main(String[] args) throws FileNotFoundException {
        Scanner scanner = new Scanner(new File("i:\\1\\2.txt"));
        scanner.useDelimiter(";|,");
        Pattern words = Pattern.compile("(CELLID=|ENSUP=|ENCHO=)");

        while (scanner.hasNextLine()) {
          String key = scanner.findInLine(words);

          while (key != null) {
            String value = scanner.next();
            if (key.equals("CELLID=")) 
              System.out.print("CELLID:" + value+"\n");
             //continue with else ifs for other keys
              else if (key.equals("ENSUP="))
            System.out.print("ENSUP:" + value+"\n");

            else if (key.equals("ENCHO="))
            System.out.print("ENCHO:" + value+"\n");
            key = scanner.findInLine(words);
          }
          scanner.nextLine();
        }

}

Большое спасибо, действительно ...

Ответы [ 3 ]

3 голосов
/ 18 января 2010

Поскольку в вашем коде есть проблемы с производительностью, вам сначала нужно найти бутылочное горлышко. Вы можете профилировать его с помощью профилировщика, доступного в используемой вами IDE.

Однако, поскольку ваш код не высок в вычислениях, но требует интенсивного ввода-вывода, как при чтении файла, так и при выводе с использованием System.out.print, я бы посоветовал вам улучшить его для улучшения ввода-вывода файла.

.

Заменить эту строку кода

Scanner scanner = new Scanner(new File("i:\\1\\2.txt"));

.

С этой строкой кода

File file = new File("i:\\1\\2.txt");
BufferedReader br = new BufferedReader( new FileReader(file)  );
Scanner scanner = new Scanner(br);

Дайте нам знать, если это поможет.

.

Поскольку предыдущее решение не очень помогло, я внес несколько изменений, чтобы улучшить ваш код. Возможно, вам придется исправить ошибки при разборе, если таковые имеются. Я смог отобразить результат анализа 392832 строк примерно за 5 секунд. Оригинальное решение занимает более 50 секунд.

Изменения указаны ниже:

  1. Использование StringTokenizer вместо Сканер
  2. Использование BufferedReader для чтения файла
  3. Использование StringBuilder для буферизации вывода

.

public class FileParse {

    private static final int FLUSH_LIMIT = 1024 * 1024;
    private static StringBuilder outputBuffer = new StringBuilder(
            FLUSH_LIMIT + 1024);
    private static final long countCellId;

    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();
        String fileName = "i:\\1\\2.txt";
        File file = new File(fileName);
        BufferedReader br = new BufferedReader(new FileReader(file));
        String line;
        while ((line = br.readLine()) != null) {
            StringTokenizer st = new StringTokenizer(line, ";|, ");
            while (st.hasMoreTokens()) {
                String token = st.nextToken();
                processToken(token);
            }
        }
        flushOutputBuffer();
        System.out.println("----------------------------");
        System.out.println("CELLID Count: " + countCellId);
        long end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));
    }

    private static void processToken(String token) {
        if (token.startsWith("CELLID=")) {
            String value = getTokenValue(token);
            outputBuffer.append("CELLID:").append(value).append("\n");
            countCellId++;
        } else if (token.startsWith("ENSUP=")) {
            String value = getTokenValue(token);
            outputBuffer.append("ENSUP:").append(value).append("\n");
        } else if (token.startsWith("ENCHO=")) {
            String value = getTokenValue(token);
            outputBuffer.append("ENCHO:").append(value).append("\n");
        }
        if (outputBuffer.length() > FLUSH_LIMIT) {
            flushOutputBuffer();
        }
    }

    private static String getTokenValue(String token) {
        int start = token.indexOf('=') + 1;
        int end = token.length();
        String value = token.substring(start, end);
        return value;
    }

    private static void flushOutputBuffer() {
        System.out.print(outputBuffer);
        outputBuffer = new StringBuilder(FLUSH_LIMIT + 1024);
    }

}

.

Обновление ENSUP и MSLH:

Мне кажется, вы включили ENSUP и MSLH в if, как указано ниже. Следовательно, вы видите значение «MSLH» для «ENSUP» и наоборот.

} else if (token.startsWith("MSLH=")) {
    String value = getTokenValue(token);
    outputBuffer.append("ENSUP:").append(value).append("\n");
} else if (token.startsWith("ENSUP=")) {
    String value = getTokenValue(token);
    outputBuffer.append("MSLH:").append(value).append("\n");
}
3 голосов
/ 18 января 2010

Простую фильтрацию текста, вероятно, легче написать на Perl (мой выбор, потому что я использую его годами) или Python (что я рекомендую новым людям, потому что это более современный язык).

0 голосов
/ 18 января 2010

Несколько решений аналогичной проблемы с использованием Java Сканер или StreamTokenizer были недавно обсуждены здесь .

...