Поиск строки в файле и запись соответствующих строк в другой файл в Java - PullRequest
6 голосов
/ 18 мая 2010

Для поиска строки в файле и записи строк с соответствующей строкой в ​​другую файл занимает 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 МБ после сжатия. Любые способы минимизировать время.

Ответы [ 5 ]

4 голосов
/ 18 мая 2010

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

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

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

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

3 голосов
/ 18 мая 2010

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

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

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

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

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

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

1 голос
/ 18 мая 2010

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

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

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

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

0 голосов
/ 18 мая 2010

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

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

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

0 голосов
/ 18 мая 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...