我已经检查了所有的在线和stackoverflow,找不到特定于此问题的匹配项。我正在尝试提取位于zip文件中的pdf文件,该文件位于zip文件内部(嵌套的压缩)。重新调用我用来提取的方法不起作用,也不改变整个程序接受输入流,而不是我下面这样做。我得到java.io.IOException: Stream Closed
。我的代码如下所示,错误行用错误消息指示。
public static void main(String[] args)
{
try
{
//Paths
String basePath = "C:\\Users\\user\\Desktop\\Scan\\";
File lookupDir = new File(basePath + "Data\\");
String doneFolder = basePath + "DoneUnzipping\\";
File[] directoryListing = lookupDir.listFiles();
for (int i = 0; i < directoryListing.length; i++)
{
if (directoryListing[i].isFile()) //there's definately a file
{
//Save the current file's path
String pathOrigFile = directoryListing[i].getAbsolutePath();
Path origFileDone = Paths.get(pathOrigFile);
Path newFileDone = Paths.get(doneFolder + directoryListing[i].getName());
//unzip it
if(directoryListing[i].getName().toUpperCase().endsWith(ZIP_EXTENSION)) //ZIP files
{
unzip(directoryListing[i].getAbsolutePath(), DESTINATION_DIRECTORY + directoryListing[i].getName());
//move to the 'DoneUnzipping' folder
Files.move(origFileDone, newFileDone);
}
}
}
} catch (Exception e)
{
e.printStackTrace(System.out);
}
}
private static void unzip(String zipFilePath, String destDir)
{
//buffer for read and write data to file
byte[] buffer = new byte[BUFFER_SIZE];
try {
FileInputStream fis = new FileInputStream(zipFilePath);
ZipInputStream zis = new ZipInputStream(fis);
ZipEntry ze = zis.getNextEntry();
while(ze != null)
{
String fileName = ze.getName();
int index = fileName.lastIndexOf("/");
String newFileName = fileName.substring(index + 1);
File newFile = new File(destDir + File.separator + newFileName);
//Zips inside zips
if(fileName.toUpperCase().endsWith(ZIP_EXTENSION))
{
try(ZipInputStream innerZip = new ZipInputStream(fis))
{
ZipEntry innerEntry = null;
while((innerEntry = innerZip.getNextEntry()) != null)
{
System.out.println("The file: " + fileName);
if(fileName.toUpperCase().endsWith("PDF"))
{
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0)
{
fos.write(buffer, 0, len);
}
fos.close();
}
}
}
}
//close this ZipEntry
zis.closeEntry(); // java.io.IOException: Stream Closed
ze = zis.getNextEntry();
}
//close last ZipEntry
zis.close();
fis.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
3条答案
按热度按时间busg9geu1#
这个问题的解决方案并不像看起来那么明显,尽管我自己以前写过一些zip实用程序,但从另一个zip文件中获取zip条目只有在回顾时才显得明显
(and第一次尝试时我也得到了
java.io.IOException: Stream Closed
)。ZipFile
和ZipInputStream
的Java类确实引导您使用文件系统,但这不是必需的。下面的函数将扫描父级zip文件,并继续扫描,直到找到指定名称的条目。(几乎)所有操作都在内存中完成。
当然,这可以修改为使用不同的搜索条件、查找多个文件类型等,并采取不同的操作,但这至少演示了所讨论的基本技术-- zip文件中的zip文件--不能保证代码的其他方面,更有经验的人很可能会改进这种风格。
qnakjoqk2#
导致您的问题的行看起来是您在读取内部zip时创建的自动关闭块:
几个可能的问题:首先它读取错误的流
fis
而不是现有的zis
。第二,你不应该在
innerZip
上使用try-with-resources来自动关闭,因为这会在退出块时隐式调用innerZip.close()
。如果你通过一个好的IDE查看ZipInputStream
的源代码,你应该看到(最终)ZipInputStream extends InflaterInputStream
本身为extends FilterInputStream
。调用innerZip.close()
将关闭底层外部流zis
(在您的情况下为fis
)因此,当您恢复外部zip的下一个条目时,流将关闭。因此,删除
try()
块并添加zis
的使用:try-catch块仅用于最外层的文件处理:
第三,在提取PDF时,您似乎复制了错误的流-使用
innerZip
而不是外部zis
。您应该能够切换到一行Files.copy
,简单地如下所示:yzuktlbb3#
你的问题是问如何使用java(在windows中隐含)从一个zip文件中提取一个pdf文件。
在许多系统包括windows中,它是一个单行命令,取决于源文件夹和目标文件夹的位置,然而,使用当前下载文件夹的最短示例,它将在 shell 中,简单如
tar -xf "german (2).zip" && tar -xf "german.zip" && german.pdf
要在windows中解释命令,请参阅How do I execute Windows commands in Java?
默认的pdf查看器可以打开结果,因此Windows Edge或在我的情况下SumatraPDF
一般来说,把pdf文件放在zip文件中是没有意义的,因为它不能在zip文件中运行,所以如果需要下载传输,建议使用单一嵌套。
没有必要为压缩文件添加密码,因为PDF使用自己的密码打开。因此增加两级复杂性是不明智的。保持简单。
如果你有多个zip嵌套在多个zip中,每个zip中有多个pdf,那么你必须通过过滤名称来更具体化,但是尽可能避免额外的洋葱皮。
您可以通过在内存或临时文件夹中运行来使其复杂化,但是使用本机文件系统是可靠且简单的,因此考虑不使用Java运行它的最快速度
这将提取所有内部压缩到工作文件夹,然后提取所有PDF文件,并删除所有必要的临时压缩。源双压缩不会被删除简单地触摸。