Zip и распаковать большой файл без загрузки всего файла в памяти в Apache Camel - PullRequest
0 голосов
/ 11 мая 2018

Мы используем Apache Camel для сжатия и распаковки наших файлов.Мы используем стандартные .marshal().gzip() и .unmarshall().gzip() API.

Наша проблема в том, что когда мы получаем действительно большие файлы, скажем, размером от 800 МБ до 1 ГБ, нашему приложению не хватает памяти, так как весь файлзагружается в память для сжатия и распаковки.

Существуют ли какие-либо библиотеки верблюжьего apis или java, которые помогут сжать / сжать файл без загрузки всего файла в память.

Похожий неотвеченныйвопрос здесь

1 Ответ

0 голосов
/ 11 мая 2018

Объяснение

Используйте другой подход: Поток файл.

То есть, не загружайте его полностью в память, а читайте его по байтам на байт и одновременно записывайте обратно байты на байт.

Получите InputStream в файл, оберните немного GZipInputStream. Чтение байта за байтом, запись в OutputStream.

Наоборот, если вы хотите сжать архив. Затем вы оборачиваете OutputStream некоторыми GZipOutputStream.


Код

В примере используется Apache Commons Compress , но логика кода остается одинаковой для всех библиотек.

Распаковка gz архива:

Path inputPath = Paths.get("archive.tar.gz");
Path outputPath = Paths.get("archive.tar");

try (InputStream fin = Files.newInputStream(inputPath );
        OutputStream out = Files.newOutputStream(outputPath);) {
    GZipCompressorInputStream in = new GZipCompressorInputStream(
        new BufferedInputStream(fin));

    // Read and write byte by byte
    final byte[] buffer = new byte[buffersize];
    int n = 0;
    while (-1 != (n = in.read(buffer))) {
        out.write(buffer, 0, n);
    }
}

Упаковка gz, архив:

Path inputPath = Paths.get("archive.tar");
Path outputPath = Paths.get("archive.tar.gz");

try (InputStream in = Files.newInputStream(inputPath);
        OutputStream fout = Files.newOutputStream(outputPath);) {
    GZipCompressorOutputStream out = new GZipCompressorOutputStream(
        new BufferedOutputStream(fout));

    // Read and write byte by byte
    final byte[] buffer = new byte[buffersize];
    int n = 0;
    while (-1 != (n = in.read(buffer))) {
        out.write(buffer, 0, n);
    }
}

Вы также можете обернуть BufferedReader и PrintWriter вокруг, если вам удобнее с ними. Они сами управляют буферизацией, и вы можете читать и писать line с вместо byte с. Обратите внимание, что это работает правильно, только если вы читаете файл со строками, а не в каком-либо другом формате.

...