2012-06-11 4 views
0

Я хочу прочитать последние n строк большого файла txt, сжатого в zip-файле, без его разархивирования.Как читать последние n строк HUGE сжатого файла без распаковки всего файла на диск

Это то, что я сейчас:

ZipFile zf = new ZipFile(file.getAbsolutePath()); 
Enumeration<?> entries = zf.entries(); 
ZipEntry ze = (ZipEntry) entries.nextElement(); 
BufferedReader in = new BufferedReader(new InputStreamReader(zf.getInputStream(ze))); 

void readLastNLines(BufferedReader bf){ 
//some code here 
} 

Я думал о пути, используя RandomAccessFile(File file, String mode), но это требует File в качестве аргумента. Zip-файл не может рассматриваться как каталог, поэтому я не могу его передать.

Любые идеи?

Оцените любую помощь и ввод.

Спасибо!

[EDIT] я выяснить менее эффективный способ достижения этой цели:

Поскольку RandomAccessFile не может быть использован, я использовал InputStream подход:

InputStream is = zf.getInputStream(ze); 
int length = is.available(); 
byte[] bytes = new byte[length]; 
int ch = -1; 
while ((ch = is.read()) != -1) { 
    bytes[--length] = (byte) ch; 
} 

String line = new String(bytes); 
//reverse the string 
String newLine = new StringBuilder(line).reverse().toString(); 

//Select how many lines do you want(some number = number of bytes) 
System.out.println(newLine.substring(line.length()-#some number#)); 
+1

Это огромная боль в заднице. Посмотрите эту тему http://stackoverflow.com/a/7322581/1417974 –

+6

вы не можете делать произвольный доступ к содержимому сжатого потока. вам нужно либо распаковать временный файл, либо выяснить, как получить то, что вам нужно, от одного прохода через поток (например, прочитать поток и сохранить последние N строк в памяти, когда вы дойдете до конца потока, у вас есть последние N строк). – jtahlborn

+1

@jtahlborn Это должен быть ответ –

ответ

1

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

+0

Возможно, вы сможете сделать это немного быстрее, если у вас есть верхняя граница числа байтов, которое могут быть в последних N строках. Вы можете искать InputStream (uncompressedSize - maxBytesInLastNLines) перед созданием InputStreamReader и BufferedReader. Это экономит вам стоимость декодирования тонны текста UTF-8 и выделения памяти для него. В любом случае, вы просто выбросите его. –

+0

@JohnWatts - вы не можете (легко) искать допустимую границу символа в многобайтовой кодировке символов. как только вы нашли точку в потоке байтов, вам нужно будет найти конец текущего символа, прежде чем вы сможете начать преобразовывать байты в символы. – jtahlborn

+0

Вы правы, что это не тривиально, но с UTF-8 это довольно просто, потому что оно самосинхронизируется. Должен признаться, я не знал этого, пока не прочитал ваш комментарий, поэтому спасибо за то, что он попросил меня посмотреть его. См. Http://stackoverflow.com/questions/4935034/how-do-i-accomplish-random-reads-of-a-utf8-file. Кроме того, я неявно предполагал, что распакованный файл был UTF-8 или ASCII. Другие кодировки могут давать другие подходы. –

0

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

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

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