Ищите строку в файле и запишите подобранные строки в другой файл в Java

Для поиска строки в файле и записи строк с совпавшей строкой в другой файл требуется 15 - 20 минут для единственного zip-файла 70 МБ (сжатое состояние). Есть ли любые способы минимизировать его.

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

получение записей zip-файла

zipFile = new ZipFile(source_file_name);

entries = zipFile.entries();

while (entries.hasMoreElements())

{ ZipEntry entry = (ZipEntry)entries.nextElement();

if (entry.isDirectory()) 
{ 
continue; 
} 
searchString(Thread.currentThread(),entry.getName(), new BufferedInputStream (zipFile.getInputStream(entry)), Out_File, search_string, stats); }

zipFile.close();

Поиск строки

public void searchString(Thread CThread, String Source_File, BufferedInputStream in, File outfile, String search, String stats) throws IOException

{ 

    int count = 0; 
    int countw = 0; 
    int countl = 0; 
    String s; 
    String[] str; 
    BufferedReader br2 = new BufferedReader(new InputStreamReader(in)); 
    System.out.println(CThread.currentThread()); 

        while ((s = br2.readLine()) != null) 
        { 
            str = s.split(search); 
            count = str.length - 1; 
            countw += count; //word count 
            if (s.contains(search)) 
            { 
            countl++;  //line count 
            WriteFile(CThread,s, outfile.toString(), search); 
            } 
        } 

    br2.close(); 
    in.close(); 


} 

--------------------------------------------------------------------------------

public void WriteFile(Thread CThread,String line, String out, String search) throws IOException

{ 
    BufferedWriter bufferedWriter = null; 
    System.out.println("writre thread"+CThread.currentThread()); 
    bufferedWriter = new BufferedWriter(new FileWriter(out, true)); 
    bufferedWriter.write(line); 
    bufferedWriter.newLine(); 
    bufferedWriter.flush(); 
} 

Пожалуйста, помогите мне. Его действительно взятие 40 минут для 10 файлов с помощью потоков и 15 - 20 минут для единственного файла 70 МБ, будучи сжатым. Любые способы минимизировать время.

6
задан Jerry Coffin 18 May 2010 в 13:46
поделиться

5 ответов

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

Вооружившись этой информацией, решите, связана ли проблема с чтением ZIP-файла, поиском или записью совпадений в выходной файл.

(Неоднократное открытие и закрытие выходного файла - плохая идея , но если вы получите лишь небольшое количество результатов поиска, это не повлияет на общую производительность.)

0
ответ дан 16 December 2019 в 21:36
поделиться

Вы повторно открываете дескриптор вывода файла для каждой отдельной строки, которую вы пишете.

Это, вероятно, окажет огромное влияние на производительность, намного перевешивая другие проблемы с производительностью. Вместо этого я бы рекомендовал создать BufferedWriter один раз (например, при первом совпадении), а затем оставить его открытым, записать каждую совпадающую строку и затем закрыть Writer по завершении.

Также удалите вызов flush () ; нет необходимости сбрасывать каждую строку, поскольку вызов Writer.close () автоматически сбрасывает все незаписанные данные на диск.

Наконец, в качестве примечания, ваш стиль именования переменных и методов не соответствует соглашению о регистре верблюдов Java; вы можете подумать об изменении этого.

4
ответ дан 16 December 2019 в 21:36
поделиться

Я не уверен, что затраты, которые вы видите, связаны с дисковыми операциями или с манипуляциями со строками. Я предположу пока, что проблема в строках, вы можете проверить это, написав тестовый драйвер, который запускает ваш код с одной и той же строкой снова и снова.

Я могу сказать, что split() будет очень дорогим в вашем случае, потому что вы создаете ненужные вам строки, а затем перерабатываете их, создавая большие накладные расходы. Возможно, вы захотите увеличить объем пространства, доступного вашей JVM, с помощью -Xmx.

Если вы просто разделяете слова по наличию пробельных символов, то вам будет гораздо лучше, если вы используете сопоставитель регулярных выражений, который вы создаете перед циклом и применяете его к строке. Количество совпадений при применении к данной строке будет вашим количеством слов, и это не должно создавать массив строк (что очень расточительно и что вы не используете). Вы увидите в JavaDocs, что split работает через регулярные выражения; это правда, но split делает дополнительный шаг по созданию отдельных строк, и именно здесь могут быть ваши потери.

Вы также можете использовать регулярное выражение для поиска совпадения вместо contains, хотя это может быть не намного быстрее.

Вы можете сделать процесс параллельным, используя несколько потоков. Однако, если split() является причиной ваших проблем, ваша проблема заключается в накладных расходах и нехватке места в куче, так что вы не обязательно получите от этого пользу.

В целом, если вам нужно делать это часто, вы можете написать сценарий на языке, более "дружелюбном" к работе со строками. 10-строчный сценарий на Python может сделать это гораздо быстрее.

3
ответ дан 16 December 2019 в 21:36
поделиться

вау, что вы делаете в этом методе

WriteFile(CThread,s, outfile.toString(), search);

каждый раз, когда вы получаете строку, содержащую ваш текст, вы создаете BufferedWriter(new FileWriter(out, true));

Просто создайте bufferedWriter в вашем searchString методе и используйте его для вставки строк. Нет необходимости открывать его снова и снова. Это значительно улучшит производительность.

1
ответ дан 16 December 2019 в 21:36
поделиться

Одна из проблем может заключаться в том, что вы перестаете читать, когда пишете. Я бы, вероятно, использовал один поток для чтения и другой поток для записи файла. В качестве дополнительной оптимизации поток, записывающий результаты, может буферизовать их в памяти и записывать их в файл как пакет, скажем, каждые десять записей или что-то в этом роде.

В потоке записи вы должны поставить в очередь входящие записи перед их обработкой.

Конечно, вам, возможно, сначала следует отладить, где это время тратится, будь то ввод-вывод или что-то еще.

0
ответ дан 16 December 2019 в 21:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: