我正在做一个程序,它只修改文件 Doc、xls、ppt 和 Vsd 中的元数据(标准和自定义),该程序工作正常,但我想知道是否有一种方法可以在不将整个文件加载到内存的情况下做到这一点:
POIFSFileSystem POIFS = new POIFSFileSystem (new FileInputStream ("file.xls"))
NPIOFSFileSystem 方法速度更快,消耗的内存更少,但它是只读的。
我正在使用 Apache POI 3.9
我正在做一个程序,它只修改文件 Doc、xls、ppt 和 Vsd 中的元数据(标准和自定义),该程序工作正常,但我想知道是否有一种方法可以在不将整个文件加载到内存的情况下做到这一点:
POIFSFileSystem POIFS = new POIFSFileSystem (new FileInputStream ("file.xls"))
NPIOFSFileSystem 方法速度更快,消耗的内存更少,但它是只读的。
我正在使用 Apache POI 3.9
您可以将所需部分映射到内存,然后使用java.nio.FileChannel
.
除了熟悉的字节通道的读、写和关闭操作之外,该类还定义了以下文件特定的操作:
可以以不影响通道当前位置的方式在文件中的绝对位置读取或写入字节。
文件的一个区域可以直接映射到内存中;对于大文件,这通常比调用通常的读取或写入方法更有效。
在您提出问题时,可悲的是没有一种非常低的记忆方式来做到这一点。好消息是,截至 2014-04-28,这是可能的!(此代码在发布时应该在 3.11 中,但现在它太新了)
既然 NPIOFS 支持写入,包括就地写入,您需要做的是:
// Open the file, and grab the entries for the summary streams
NPOIFSFileSystem poifs = new NPOIFSFileSystem(file, false);
DocumentNode sinfDoc =
(DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
DocumentNode dinfDoc =
(DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
// Open and parse the metadata
SummaryInformation sinf = (SummaryInformation)PropertySetFactory.create(
new NDocumentInputStream(sinfDoc));
DocumentSummaryInformation dinf = (DocumentSummaryInformation)PropertySetFactory.create(
new NDocumentInputStream(dinfDoc));
// Make some metadata changes
sinf.setAuthor("Changed Author");
sinf.setTitle("Le titre \u00e9tait chang\u00e9");
dinf.setManager("Changed Manager");
// Update the metadata streams in the file
sinf.write(new NDocumentOutputStream(sinfDoc));
dinf.write(new NDocumentOutputStream(dinfDoc));
// Write out our changes
fs.writeFilesystem();
fs.close();
您应该能够在文件大小的 20% 以下的内存中完成所有这些操作,这很可能比较大文件的内存要少!
(如果您想了解更多信息,请查看ModifyDocumentSummaryInformation 示例和HPSF TestWrite 单元测试)