我正在做一个程序,只修改文件Doc、xls、ppt和Vsd中的元数据(标准和自定义),该程序工作正常,但我想知道是否有一种方法可以在不将整个文件加载到内存的情况下做到这一点:
POIFSFileSystem POIFS=新POIFSFile系统(新FileInputStream("file.xls"))
NPOIFSFileSystem方法速度更快,占用的内存更少,但它是只读的。
我使用的是Apache POI 3.9
您可以将所需的零件映射到内存,然后使用java.nio.FileChannel
进行处理。
除了熟悉的字节通道的读、写和关闭操作外,这个类还定义了以下特定于文件的操作:
可以在文件中的绝对位置读取或写入字节,而不会影响通道的当前位置。
文件的区域可以直接映射到存储器中;对于大文件,这通常比调用通常的读或写方法效率高得多。
在你提出这个问题时,遗憾的是,没有一种记忆力很低的方法可以做到这一点。好消息是,截至2014-04-28,这是可能的!(这个代码发布时应该是3.11版本,但现在还太新了)
既然NPOIFS支持写入,包括就地写入,那么您想要做的是:
// 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 changu00e9");
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示例和HPSFTestWrite单元测试)