Читать файл OLE2 на Java без буферизации в памяти?

#apache-poi

#apache-poi

Вопрос:

Я использую Apache POI для чтения файла OLE2 (может быть Word, может быть Excel). Используя POIFSFileSystem, я могу открыть файл и прочитать содержимое. С этим все в порядке.

Однако, похоже, он использует довольно много памяти. Глядя на несколько битов POIF, кажется, что различные биты файла буферизуются в памяти, иногда более одного раза.

Возможно ли просто считывать биты из файла, не загружая все это сразу? Я заметил, что с новыми форматами файлов (ooxml) у вас есть выбор между файлом и входным потоком, а в документах конструктор файла указан как меньший объем памяти. Есть ли что-то подобное для более старых POIF-файлов OLE2?

Я использую POI 3.7 Final на случай, если это имеет значение!

Ответ №1:

Вам повезло, это можно сделать, но, увы, вам нужно будет перейти на бета-версию — код появился после финальной версии 3.7. Вас должна устраивать 3.8 beta 2, но, возможно, вы захотите дождаться 3.8 beta 3, если сможете, поскольку над кодом все еще ведется работа.

Что вам нужно сделать, так это переключиться с использования POIFSFileSystem на NPOIFSFileSystem. Префикс N предназначен для нового OLE2-кода на основе NIO, который более эффективно использует память при использовании потока и намного эффективнее при использовании файла. Смотрите документы NPOIFSFileSystem для получения более подробной информации.

Ваш код должен быть чем-то вроде:

 // This is the most memory efficient way to open the FileSystem
NPOIFSFileSystem fs;
try {
    fs = new NPOIFSFileSystem(new File(filename));
} catch (IOException e) {
    // an I/O error occurred, or the File did not provide a compatible
    // POIFS data structure
}
DirectoryEntry root = fs.getRoot();
  

В 3.8 beta 2 большинство классов POIDocument (HSSFWorkbook и т.д.) Будут принимать DirectoryEntry в своем конструкторе, Поэтому вы можете читать их из NPOIFSFileSystem. Однако поддержка записи еще не совсем завершена, поэтому вам нужно будет придерживаться POIFSFileSytem, если вам нужно выполнить обратную запись (с большим объемом памяти)