Найти строку в очень большом отформатированном текстовом файле в Java

1

Вот что: у меня действительно большой текстовый файл, и у него есть такой формат:

0007476|000011434982|00249626000|R|2008-01-11 00:00:00|9999-12-31 23:59:59|000019.99
0007476|000014017887|00313865000|R|2011-04-19 00:00:00|9999-12-31 23:59:59|000599.99
...
...

И мне нужно найти, существует ли конкретный шаблон в файле, скажем,

0007476|whatever|00313865000|whatever

Все, что мне нужно, это логическое высказывание "да" или "нет". Теперь я сделал это, чтобы прочитать файл по строкам и выполнить регулярное выражение:

Pattern pattern = Pattern.compile(regex);
Scanner scanner = new Scanner(new File(fileName));
        String line;
        while (scanner.hasNextLine()) {
            line = scanner.nextLine();
            if (pattern.matcher(line).matches()) {
                scanner.close();
                return true;
            }
        }

и регулярное выражение имеет форму

"0007476\|\d{12}\|0031386500.*

Этот метод работает, но обычно требуется 15 секунд для поиска строки, которая далека от начальной строки. Есть ли более быстрый способ достичь этого? благодаря

  • 2
    Это, вероятно, оптимальное регулярное выражение. Кроме того, подумайте над тем, чтобы задавать вопросы, которые требуют улучшения существующего, рабочего кода при проверке кода .
Теги:

2 ответа

1

Класс java String имеет метод contains, который возвращает логическое значение. Если ваша строка исправлена, это намного быстрее, чем регулярное выражение:

if (string.contains("0007476|") && string.contains("|00313865000|")) {
   // whatever
}

Надеюсь, что помогло, если нет, оставить комментарий.

  • 0
    Спасибо за ответ. Я пробовал это, но разница в скорости незначительна. Максимум 500 мс, а чтение файла занимает более 20 секунд.
  • 0
    Вы профилировали свой код? Вы знаете, где находится узкое место?
1

Я предполагаю, что вам нужен Scanner потому что файл слишком велик, чтобы читать в одну String?

Если это не так, вы можете использовать регулярное выражение, которое находит соответствие напрямую. В зависимости от того, насколько вы заботитесь о конкретном тексте в начале строки, вы можете что-то сделать следующим образом:

"(?m)^0007476\|\d{12}\|0031386500.*$

Если вам нужно разбить его на более мелкие куски из-за использования памяти, я бы предложил не читать по одной строке, (поскольку строки довольно короткие), но обрабатывают большие куски, используя вместо этого что-то вроде BufferedReader?


Я немного поиграл с файлом 1,25 ГБ, а следующее примерно в 2,5 раза быстрее, чем ваша реализация:

private static boolean matches() throws IOException {
   String regex = "(?m)^0007476\|\d{12}\|0031386500.*$";
   Pattern pattern = Pattern.compile(regex);

   try(BufferedReader br = new BufferedReader(new FileReader(FILENAME))) {
      for(String lines; (lines = readLines(br, 10000)) != null; ) {
         if (pattern.matcher(lines).find()) {
            return true;
         }
      }
   }

   return false;
}

private static String readLines(BufferedReader br, int amount) throws IOException {
   StringBuilder builder = new StringBuilder();
   int lineCounter = 0;
   for(String line; (line = br.readLine()) != null && lineCounter < amount; lineCounter++ ) {
      builder.append(line).append(System.lineSeparator());
   }

    return lineCounter > 0 ? builder.toString() : null;
}
  • 0
    Размер файла превышает 1 ГБ, поэтому он должен быть разделен на куски. Может быть, есть способ сделать так, чтобы куски содержали не одну строку, а несколько строк вместе?
  • 0
    О, я вижу использование BufferedReader. Собираюсь попробовать это. Спасибо.
Показать ещё 7 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню