GZIP в Matlab для больших файлов

У меня есть функция, которая распаковывает массив байтов Z это было упаковано с использованием библиотеки zlib (адаптировано здесь).

  • Размер упакованных данных составляет 4,11 ГБ, а распакованных - 6,65 ГБ. У меня 32 ГБ памяти, так что это намного ниже предела.
  • Я попытался увеличить размер кучи Java до 15,96 ГБ, но это не помогло.
  • Переменная среды MATLAB_JAVA указывает на jre1.8.0_144.

Я получаю загадочную ошибку

'MATLAB array exceeds an internal Java limit.' 

во 2-й строке этого кода:

import com.mathworks.mlwidgets.io.InterruptibleStreamCopier
a=java.io.ByteArrayInputStream(Z);
b=java.util.zip.GZIPInputStream(a);
isc = InterruptibleStreamCopier.getInterruptibleStreamCopier;
c = java.io.ByteArrayOutputStream;
isc.copyStream(b,c);
M=typecast(c.toByteArray,'uint8');

Попытка реализовать предложение Марка Адлера:

Z=reshape(Z,[],8);
import com.mathworks.mlwidgets.io.InterruptibleStreamCopier
a=java.io.ByteArrayInputStream(Z(:,1));
b=java.util.zip.GZIPInputStream(a);
for ct = 2:8,b.read(Z(:,ct));end
isc = InterruptibleStreamCopier.getInterruptibleStreamCopier;
c = java.io.ByteArrayOutputStream;
isc.copyStream(b,c);

Но на этом isc.copystream Я получаю эту ошибку:

Java exception occurred:
java.io.EOFException: Unexpected end of ZLIB input stream

    at java.util.zip.InflaterInputStream.fill(Unknown Source)

    at java.util.zip.InflaterInputStream.read(Unknown Source)

    at java.util.zip.GZIPInputStream.read(Unknown Source)

    at java.io.FilterInputStream.read(Unknown Source)

    at com.mathworks.mlwidgets.io.InterruptibleStreamCopier.copyStream(InterruptibleStreamCopier.java:72)

    at com.mathworks.mlwidgets.io.InterruptibleStreamCopier.copyStream(InterruptibleStreamCopier.java:51)

Читая напрямую из файла, я пытался прочитать данные прямо из файла.

streamCopier = com.mathworks.mlwidgets.io.InterruptibleStreamCopier.getInterruptibleStreamCopier;
fileInStream = java.io.FileInputStream(java.io.File(filename));
fileInStream.skip(datastart);
gzipInStream = java.util.zip.GZIPInputStream( fileInStream );
baos = java.io.ByteArrayOutputStream;
streamCopier.copyStream(gzipInStream,baos);
data = baos.toByteArray;
baos.close;
gzipInStream.close;
fileInStream.close;

Хорошо работает для небольших файлов, но с большими файлами я получаю:

Java exception occurred:
java.lang.OutOfMemoryError

на линии streamCopier.copyStream(gzipInStream,baos);

2 ответа

Решение

Узким местом является размер каждого создаваемого Java-объекта. Это происходит в java.io.ByteArrayInputStream(Z) поскольку массив MATLAB не может быть передан в Java без преобразования, а также в copyStreamгде данные фактически копируются в выходной буфер / память. У меня была похожая идея разбивать объекты на куски допустимого размера ( src):

function chunkDunzip(Z)
%% Imports:
import com.mathworks.mlwidgets.io.InterruptibleStreamCopier
%% Definitions:
MAX_CHUNK = 100*1024*1024; % 100 MB, just an example
%% Split to chunks:
nChunks = ceil(numel(Z)/MAX_CHUNK);
chunkBounds = round(linspace(0, numel(Z), max(2,nChunks)) );

V = java.util.Vector();
for indC = 1:numel(chunkBounds)-1
  V.add(java.io.ByteArrayInputStream(Z(chunkBounds(indC)+1:chunkBounds(indC+1))));
end

S = java.io.SequenceInputStream(V.elements);  
b = java.util.zip.InflaterInputStream(S);

isc = InterruptibleStreamCopier.getInterruptibleStreamCopier;
c = java.io.FileOutputStream(java.io.File('D:\outFile.bin'));
isc.copyStream(b,c);
c.close();

end

Несколько заметок:

  1. Я использовал FileOutputStream так как он не попадает во внутренний предел объектов Java (насколько мои тесты прошли).
  2. Увеличение памяти кучи Java все еще требуется.
  3. Я продемонстрировал это с помощью deflate, а не gzip. Решение для gzip очень похоже - если это проблема, я изменю ее.

Вам не нужно читать все сразу. Вы можете повторить b.read() вызовов, где вы предоставляете байтовый массив определенной заданной длины. Повторяйте, пока не вернет -1. Используйте полученные куски для построения вашего результата в гигантском массиве MATLAB, а не в гигантском массиве Java.

Другие вопросы по тегам