java - 使用 Java 从 DOC 文件中提取嵌入式 ZIP
问题描述
我有一个包含多个嵌入文件的 DOC 文件。此文件中嵌入了 PDF、DOC 和 ZIP。我已经使用 Apache POI 来钻取 POIFS。我可以提取 OLE10 文件信息、原始文件名、路径、大小等。
我遇到困难的地方是在从文档中提取 ZIP 文件的过程中。我使用 DocumentInputStream 复制到带有 IOUtils 的 FileOutputStream。
// Load the file object and embedded file system
File file = new File(filePathBuilder.toString());
POIFSFileSystem wordDocFS = new POIFSFileSystem(new FileInputStream(file));
DirectoryNode docRootDir = wordDocFS.getRoot();
// Read ROOT POIFS
Iterator<Entry> docRootDirIter = docRootDir.getEntries();
while(docRootDirIter.hasNext()){
Entry docRootDirEntry = docRootDirIter.next();
if (docRootDirEntry.getName().contains("ObjectPool")){
objPoolDir = (DirectoryNode) docRootDirEntry;
// Read ObjectPool POIFS directory ---> ObjectPool is location of embedded files within a DOC file
Iterator<Entry> objPoolDirIter = objPoolDir.getEntries();
while(objPoolDirIter.hasNext()){
Entry objPoolDirEntry = objPoolDirIter.next();
// Read ObjectPool POIFS subdirectories
if(objPoolDirEntry.isDirectoryEntry()){
DirectoryNode objPoolSubDir = (DirectoryNode) objPoolDirEntry;
Iterator<Entry> objPoolSubDirIter = objPoolSubDir.getEntries();
while (objPoolSubDirIter.hasNext()){
Entry objPoolSubDirEntry = objPoolSubDirIter.next();
// Read embedded OLE10 files, create an OLE object, and read into an ArrayList of OLE objects
if (objPoolSubDirEntry.isDocumentEntry()){
DocumentEntry objPoolSubDirFile = (DocumentEntry) objPoolSubDirEntry;
if((objPoolSubDirFile.getSize() < 15_000_000)
&& (objPoolSubDirFile.getName().contains("Ole10Native"))){
Ole10Native oleEntry = Ole10Native.createFromEmbeddedOleObject(objPoolSubDir);
OleEntry oleObject = new OleEntry();
String oleFqdn = oleEntry.getFileName();
//System.out.println(oleFqdn+"\t"+oleFqdn.endsWith("zip"));
int oleSize = oleEntry.getDataSize();
String olePath = oleFqdn.substring(
0,
oleFqdn.lastIndexOf("\\")+1
);
String oleFilename = oleFqdn.substring(
oleFqdn.lastIndexOf("\\")+1
);
String oleFileType = oleFqdn.substring(
oleFqdn.lastIndexOf(".")+1
);
oleObject.setFileFQDN(oleFqdn);
oleObject.setFilePath(olePath);
oleObject.setFileName(oleFilename);
oleObject.setFileExtension(oleFileType);
oleObject.setFileSize(oleSize);
if(oleObject.getFileName().contains("game_report")){
String streamFileName = "C:\\Users\\ra069466\\Documents\\Software_Projects\\Maint_Tool_test_files\\testOLE\\"
+oleObject.getFileName();
InputStream inStream = new DocumentInputStream(objPoolSubDirFile);
OutputStream outStream = new FileOutputStream(streamFileName);
IOUtils.copy(inStream,outStream);
System.out.println("Wrote out: "
+streamFileName);
}
oleEntryList.add(oleObject);
}
}
}
}
}
}
}
它似乎可以复制,但我的操作系统无法将 ZIP 文件识别为存档。
我尝试将 IOUtils.copy() 设置为输出 ZipOutputStream,但仍然没有成功。我收到“java.util.zip.ZipException:没有当前 ZIP 条目”。我完全不知道如何提取 ZIP 文件并将其写为我可以打开的 ZIP 存档。
解决方案
@NormR,感谢您的帮助!在第一个 PK 记录之前通过 InputStream.skip() 删除多余的字符解决了这个问题。我能够从 Word DOC 中提取嵌入的 ZIP 文件并将它们写入本地。而且,我现在能够从 ZipFiles 中提取 ZipEntries 以进行正确处理。
推荐阅读
- java - 使用 Java lambda 或流将 POJO 列表转换为其 ID 列表
- bash - 重命名从 PDF 文件的 csv 列表创建的目录
- python - TensorFlow 的 map_fn 只在 CPU 上运行
- web-applications - 如何在 splitwise 中获取 ACCESS_TOKEN
- mysql - SQL 插入不起作用
- node.js - 如何使用单个代码库为桌面、Web 和移动设备创建 node.js 应用程序?
- c# - 使用 Xamarin 进行 FireBase 身份验证
- android - 使用 android volley(POST 方法)时出现此错误:java.net.ConnectException:无法连接到 /192.168.0.2:4000
- eclipse - Git:如何在 git log --pretty=format... 中包含工作树状态?
- java - ScenicView Javafx java.lang.UnsatisfiedLinkError