Java 如何在不将整个文件解压缩到磁盘的情况下读取一个巨大压缩文件的最后n行

Java 如何在不将整个文件解压缩到磁盘的情况下读取一个巨大压缩文件的最后n行,java,file-io,compression,Java,File Io,Compression,我想读取压缩在zip文件中的大txt文件的最后n行,而不解压缩它 这就是我现在拥有的: ZipFile zf = new ZipFile(file.getAbsolutePath()); Enumeration<?> entries = zf.entries(); ZipEntry ze = (ZipEntry) entries.nextElement(); BufferedReader in = new BufferedReader(new InputStreamReader(zf

我想读取压缩在zip文件中的大txt文件的最后n行,而不解压缩它

这就是我现在拥有的:

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
}

像解密和二进制反序列化这样的压缩只能从一开始就完成。有一些形式的压缩,您可以这样做,但只有最简单的形式。(Zip和Jar不是这些的例子)这是因为你不知道字节是什么意思,除非你读了它们前面的一些字节,通常是所有字节


如果您想访问“文件”的压缩部分,您需要将其分解为更小的部分,这些部分可以单独解压缩。

您不能对压缩流内容进行随机访问。您需要解压缩到一个临时文件,或者找到一种方法从流的一次传递中获取所需内容(例如,读取流并将最后N行保留在内存中,当您到达流的末尾时,您拥有最后N行).

这是一个巨大的麻烦。查看此线程,您无法对压缩流内容进行随机访问。您需要解压缩到一个临时文件,或者找到一种方法从流的一次传递中获取所需内容(例如,读取流并将最后N行保留在内存中,当您到达流的末尾时,您拥有最后N行)@jtahlborn这应该是一个答案任何人都有一个更有效的方法来做到这一点吗?如果你对最后N行的字节数有一个上限,你也许可以让它更快一点。在创建InputStreamReader和BufferedReader之前,可以将InputStream搜索到(uncompressedSize-maxBytesInLastNLines)。这节省了解码大量UTF-8文本并为其分配内存的成本。无论如何,你都要扔掉它。@JohnWatts-在多字节字符编码中,你不能(很容易)找到一个有效的字符边界。一旦在字节流中找到了点,就必须先找到当前字符的结尾,然后才能开始将字节转换为字符。没错,这并不简单,但使用UTF-8实际上很容易,因为它是自同步的。我必须承认,在我读到你的评论之前我并不知道这一点,所以谢谢你提醒我去查阅。看见另外,我隐式地假设解压缩的文件是UTF-8或ASCII。其他编码可能会产生其他方法。谢谢您的建议,我正在尝试使用
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#));