2012-05-24 2 views
4

Я работаю над проектом, который работает на очень большом количестве данных. У меня есть много (тысяч) почтовых файлов, каждый из которых содержит ОДИН простой текстовый файл с тысячами строк (около 80 тыс. Строк). То, что я сейчас делаю это следующее:Чтение файла zip эффективно в Java

for(File zipFile: dir.listFiles()){ 
ZipFile zf = new ZipFile(zipFile); 
ZipEntry ze = (ZipEntry) zf.entries().nextElement(); 
BufferedReader in = new BufferedReader(new InputStreamReader(zf.getInputStream(ze))); 
... 

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

Я искал другой подход, но я ничего не смог найти. Я думаю, что я должен использовать API-интерфейсы java nio, предназначенные для интенсивных операций ввода-вывода, но я не знаю, как их использовать с zip-файлами.

Любая помощь будет действительно оценена.

Спасибо,

Marco

+0

Насколько велики файлы? Сколько времени требуется, чтобы прочитать их, используя этот код? Сколько времени требуется, чтобы скопировать их в '/ dev/null'? – NPE

+2

Вы должны сначала определить, потрачено ли большинство вашего времени на чтение из zip-файлов или обработка строк текста. Что вы делаете с каждой строкой в ​​текстовых файлах? –

+0

@aix Зашифрованные файлы составляют около 30 МБ каждый, а txt внутри zip-файла - около 60/70 МБ. Либо размер и количество строк не фиксированы, они могут меняться, но теоретически они должны быть всегда одинаковыми по размеру и количеству строк. Чтение и обработка файлов с помощью этого кода занимает много часов, около 15, но это зависит от многих факторов. –

ответ

3

У меня есть много (тысяч) почтовых файлов. Зашифрованные файлы составляют около 30 МБ каждый, а txt внутри zip-файла - около 60/70 МБ. Чтение и обработка файлов с помощью этого кода занимает много часов, около 15, но это зависит.

Давайте сделаем некоторые расчеты на основе конверта.

Предположим, у вас есть 5000 файлов. Если для их обработки требуется 15 часов, это равно ~ 10 секунд на файл. Файлы составляют около 30 МБ каждый, поэтому пропускная способность составляет ~ 3 МБ/с.

Это на один и два порядка медленнее, чем скорость, с которой ZipFile может декомпрессировать материал.

Либо есть проблема с дисками (они локальны, или общий сетевой ресурс?), Или это фактическая обработка, которая занимает большую часть времени.

Лучший способ узнать это - использовать профилировщик.

+0

Ну, вот в чем дело. В настоящее время я работаю над небольшой частью общих файлов: я искренне не помню время, необходимое для их обработки, ни время, затрачиваемое на обработку ВСЕГО файла (не только те, что у меня есть). Во всяком случае, мы говорим о часах. Однако я хотел бы знать, что является лучшим эффективным способом для чтения этих файлов. С API Java nio мы можем эффективно читать файлы с использованием файловых каналов, но это не представляется возможным с zip-файлами. Если вы знаете, есть ли возможность сделать это с другими видами сжатых файлов вместо почтовых индексов, пожалуйста, дайте мне знать. Спасибо, Marco –

0

Вы можете использовать новый файл API, как это:

Path jarPath = Paths.get(...); 
try (FileSystem jarFS = FileSystems.newFileSystem(jarPath, null)) { 
    Path someFileInJarPath = jarFS.getPath("/..."); 
    try (ReadableByteChannel rbc = Files.newByteChannel(someFileInJarPath, EnumSet.of(StandardOpenOption.READ))) { 
     // read file 
    } 
} 

Код для файлов .jar, но я думаю, что он должен работать на молнии, а также.

+0

Не ответ. Он утверждает, что его время потрачено * на чтение * файлов, а не на их поиск. – EJP

+0

? OP явно попросил подход «java nio APIs». С другой стороны, OP, возможно, искал подход java.nio.channels, а не java.nio.file. – Puce

+0

Я обновил свой пример, чтобы использовать API java.nio.channels. Однако я не проводил анализ производительности и не знаю, поможет ли это в этом случае. Тем не менее, java.nio.file является предпочтительным API в Java SE 7. – Puce

0

Вы можете попробовать этот код

try 
    { 

     final ZipFile zf = new ZipFile("C:/Documents and Settings/satheesh/Desktop/POTL.Zip"); 

     final Enumeration<? extends ZipEntry> entries = zf.entries(); 
     ZipInputStream zipInput = null; 

     while (entries.hasMoreElements()) 
     { 
      final ZipEntry zipEntry=entries.nextElement(); 
      final String fileName = zipEntry.getName(); 
     // zipInput = new ZipInputStream(new FileInputStream(fileName)); 
      InputStream inputs=zf.getInputStream(zipEntry); 
      // final RandomAccessFile br = new RandomAccessFile(fileName, "r"); 
       BufferedReader br = new BufferedReader(new InputStreamReader(inputs, "UTF-8")); 
       FileWriter fr=new FileWriter(f2); 
      BufferedWriter wr=new BufferedWriter(new FileWriter(f2)); 

      while((line = br.readLine()) != null) 
      { 
       wr.write(line); 
       System.out.println(line); 
       wr.newLine(); 
       wr.flush(); 
      } 
      br.close(); 
      zipInput.closeEntry(); 
     } 


    } 
    catch(Exception e) 
    { 
     System.out.print(e); 
    } 
    finally 
    { 
     System.out.println("\n\n\nThe had been extracted successfully"); 

    } 

этот код работает в хорошей форме.

0

Правильный способ итерацию почтовый файл

final ZipFile file = new ZipFile(FILE_NAME); 
try 
{ 
final Enumeration<? extends ZipEntry> entries = file.entries(); 
while (entries.hasMoreElements()) 
{ 
    final ZipEntry entry = entries.nextElement(); 
    System.out.println(entry.getName()); 
    //use entry input stream: 
    readInputStream(file.getInputStream(entry)) 
} 
} 
finally 
{ 
file.close(); 
} 

private static int readInputStream(final InputStream is) throws IOException { 
final byte[] buf = new byte[ 8192 ]; 
int read = 0; 
int cntRead; 
while ((cntRead = is.read(buf, 0, buf.length)) >=0 ) 
{ 
    read += cntRead; 
} 
return read; 
} 

Zip файл состоит из нескольких записей, каждая из них имеет поле, содержащее число байтов в текущей записи. Таким образом, легко итератировать все записи в zip-файле без фактической декомпрессии данных. java.util.zip.ZipFile принимает имя файла/файла и использует произвольный доступ для перехода между позициями файла. java.util.zip.ZipInputStream, с другой стороны, работает с потоками, поэтому он не может свободно прыгать.Вот почему он должен читать и распаковывать все данные zip, чтобы получить EOF для каждой записи и прочитать следующий заголовок записи.

Что это значит? Если у вас уже есть zip-файл в вашей файловой системе - используйте ZipFile для его обработки независимо от вашей задачи. В качестве бонуса вы можете получить доступ к записям zip как последовательно, так и произвольно (с небольшим штрафом за производительность). С другой стороны, если вы обрабатываете поток, вам нужно будет обрабатывать все записи последовательно с помощью ZipInputStream.

Вот пример. Zip-архив (общий размер файла = 1,6 ГБ), содержащий три записи 0,6 ГБ, повторялся через 0,05 сек с использованием ZipFile и через 18 секунд использовался ZipInputStream.

+0

Скопировать с наклейки http://java-performance.info/how-to-iterate-zip-file-records/ – plastique

0

Корпорация Intel разработала улучшенную версию zlib, в которой Java использует внутреннюю переформатировку zip/unzip. Это требует, чтобы вы исправляли источники zlib с помощью Interl's IPP paches. Я сделал benchmark с пропускной способностью от 1.4x до 3x.

Смежные вопросы