gpt4 book ai didi

java - 如何在不使用临时文件的情况下从 Java 中的嵌套 zip 文件中读取数据?

转载 作者:行者123 更新时间:2023-12-05 00:48:59 35 4
gpt4 key购买 nike

我正在尝试从嵌套的 zip 存档中提取文件并在内存中处理它们。

这个问题不是关于什么:

  1. 如何在 Java 中读取 zip 文件:不,问题是如何在 zip 中读取 zip 文件中的 zip 文件,依此类推(如嵌套 zip 文件中)。

  2. 在磁盘上写入临时结果:不,我要在内存中完成所有操作。我使用将结果临时写入磁盘的效率不高的技术找到了许多答案,但这不是我想要做的。

例子:

Zipfile -> Zipfile1 -> Zipfile2 -> Zipfile3

目标:提取每个嵌套 zip 文件中的数据,全部在内存中并使用 Java。

ZipFile是答案,你说?不,不是,它适用于第一次迭代,即:

Zipfile -> Zipfile1

但是一旦你到达 Zipfile2,并执行:

ZipInputStream z = new ZipInputStream(zipFile.getInputStream( zipEntry) ) ;

你会得到一个 NullPointerException。

我的代码:

public class ZipHandler {

String findings = new String();
ZipFile zipFile = null;

public void init(String fileName) throws AppException{

try {
//read file into stream
zipFile = new ZipFile(fileName);
Enumeration<?> enu = zipFile.entries();
exctractInfoFromZip(enu);

zipFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();

} catch (IOException e) {
e.printStackTrace();
}
}

//The idea was recursively extract entries using ZipFile
public void exctractInfoFromZip(Enumeration<?> enu) throws IOException, AppException{

try {
while (enu.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry) enu.nextElement();

String name = zipEntry.getName();
long size = zipEntry.getSize();
long compressedSize = zipEntry.getCompressedSize();

System.out.printf("name: %-20s | size: %6d | compressed size: %6d\n",
name, size, compressedSize);

// directory ?
if (zipEntry.isDirectory()) {
System.out.println("dir found:" + name);
findings+=", " + name;
continue;
}

if (name.toUpperCase().endsWith(".ZIP") || name.toUpperCase().endsWith(".GZ")) {
String fileType = name.substring(
name.lastIndexOf(".")+1, name.length());

System.out.println("File type:" + fileType);
System.out.println("zipEntry: " + zipEntry);

if (fileType.equalsIgnoreCase("ZIP")) {
//ZipFile here returns a NULL pointer when you try to get the first nested zip
ZipInputStream z = new ZipInputStream(zipFile.getInputStream(zipEntry) ) ;
System.out.println("Opening ZIP as stream: " + name);

findings+=", " + name;

exctractInfoFromZip(zipInputStreamToEnum(z));
} else if (fileType.equalsIgnoreCase("GZ")) {
//ZipFile here returns a NULL pointer when you try to get the first nested zip
GZIPInputStream z = new GZIPInputStream(zipFile.getInputStream(zipEntry) ) ;
System.out.println("Opening ZIP as stream: " + name);

findings+=", " + name;

exctractInfoFromZip(gZipInputStreamToEnum(z));
} else
throw new AppException("extension not recognized!");
} else {
System.out.println(name);
findings+=", " + name;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println("Findings " + findings);
}

public Enumeration<?> zipInputStreamToEnum(ZipInputStream zStream) throws IOException{

List<ZipEntry> list = new ArrayList<ZipEntry>();

while (zStream.available() != 0) {
list.add(zStream.getNextEntry());
}

return Collections.enumeration(list);
}

最佳答案

我没有尝试过,但使用 ZipInputStream您可以读取任何包含 ZIP 文件作为数据的 InputStream。遍历条目,当您找到正确的条目时,使用 ZipInputStream创建另一个嵌套的ZipInputStream`。

以下代码演示了这一点。想象一下,我们在 0.zip 中有一个 readme.txt,它再次被压缩在 1.zip 中,而 1.zip 又被压缩在 2.zip 。现在我们从 readme.txt 中读取一些文本:

try (FileInputStream fin = new FileInputStream("D:/2.zip")) {
ZipInputStream firstZip = new ZipInputStream(fin);
ZipInputStream zippedZip = new ZipInputStream(findEntry(firstZip, "1.zip"));
ZipInputStream zippedZippedZip = new ZipInputStream(findEntry(zippedZip, "0.zip"));

ZipInputStream zippedZippedZippedReadme = findEntry(zippedZippedZip, "readme.txt");
InputStreamReader reader = new InputStreamReader(zippedZippedZippedReadme);
char[] cbuf = new char[1024];
int read = reader.read(cbuf);
System.out.println(new String(cbuf, 0, read));
.....

public static ZipInputStream findEntry(ZipInputStream in, String name) throws IOException {
ZipEntry entry = null;
while ((entry = in.getNextEntry()) != null) {
if (entry.getName().equals(name)) {
return in;
}
}
return null;
}

请注意,代码真的很丑陋,它不会关闭任何东西,也不会检查错误。它只是一个演示其工作原理的最小化版本。

理论上,您级联到另一个 ZipInputStream 的数量是没有限制的。数据永远不会写入临时文件。仅当您读取每个 InputStream 时,才按需执行解密。

关于java - 如何在不使用临时文件的情况下从 Java 中的嵌套 zip 文件中读取数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47208932/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com