Java Zip-файл, созданный с помощью ByteArrayOutputStream, меньше, чем с FileOutputStream - PullRequest
0 голосов
/ 09 января 2020

Выход Zip-файла при использовании ByteArrayOuputStream меньше, чем у FileOutputStream.

В Java Я создаю Zip-файл. Который открывается успешно, когда я использую FileOutputStream.

При переключении FileOutputStream на ByteArrayOutputStream я получаю немного меньший файл, около 221 байта. И этот файл не открывается, но имеет то же содержимое, что и другие, но пропускает 221 байт.

Лог c, который я использую для создания Zip-файла, одинаков в обоих случаях. Поэтому я поделюсь основными логиками c без создания zip (дайте мне знать, если вам это нужно).

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        zipOS = new ZipOutputStream(baos);

Затем я создаю Zip-файл, а затем ...

        zipOS.flush();
        baos.flush();
        baos.writeTo(new FileOutputStream("TEST_AS_BYTESTREAM_1.zip"));
        zipOS.close();
        baos.close();

Я использую baos.writeTo (), чтобы обойти это, чтобы доказать, что проблема связана не с ответом HTTP, а с элементом ByteArrayOutputStream.

При использовании baos.writeTo(new FileOutputStream("TEST_AS_BYTESTREAM_1.zip")); я получаю файл меньшего размера, который не не открываются как Zip.

Этот лог c находится в java контроллере, так что ссылка, нажатая на веб-страницу, будет загружать zip-файл, не касаясь файловых систем, за исключением пользователей.

Вот код, использующий FileOutputStream, который работает ...

        FileOutputStream baos = new FileOutputStream("TEST_AS_FILE.zip");
        zipOS = new ZipOutputStream(baos);

Помимо второго фрагмента кода не имеет значения, так как мне нужно будет отправить файл, созданный на веб-сервере. Но дело в том, что поток Fileoutput с теми же логами c и ByteArrayOutputStream имеет разницу.

Ответы [ 2 ]

3 голосов
/ 09 января 2020

Следующее утверждение неверно:

baos.writeTo(new FileOutputStream("TEST_AS_BYTESTREAM_1.zip"));

Javado c из writeTo(OutputStream out) ничего не говорит о закрытии OutputStream, что означает, что это не так , так что последние данные все еще находятся в буферизованном виде в незамкнутом, незараженном виде FileOutputStream.

Правильный путь:

try (OutputStream out = new FileOutputStream("TEST_AS_BYTESTREAM_1.zip")) {
    baos.writeTo(out);
}

Также ByteArrayOutputStream не нужно закрывать или промывать. Как говорит джавадо c из close():

Закрытие ByteArrayOutputStream не имеет никакого эффекта.

Однако вам понадобится позвонить finish() на ZipOutputStream, чтобы завершить содержание. Поскольку закрытие потока zip автоматически завершает его для вас, правильный способ сделать это:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream zipOS = new ZipOutputStream(baos)) {
    // create the Zip file content here
}
try (OutputStream out = new FileOutputStream("TEST_AS_BYTESTREAM_1.zip")) {
    baos.writeTo(out);
}

При записи непосредственно в файл:

try (ZipOutputStream zipOS = new ZipOutputStream(new FileOutputStream("TEST_AS_FILE.zip"))) {
    // create the Zip file content here
}

Рассмотрите возможность добавления BufferedOutputStream для лучшей производительности.

0 голосов
/ 09 января 2020

Окончательный ответ следующий. Большое спасибо за ответ, данный ранее.

В основном мне нужно было использовать метод .fini sh () объекта ZipOuputStream. Все остальное осталось прежним.

Код предварительного создания почтового индекса такой же, как и раньше

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        zipOS = new ZipOutputStream(baos);

Создание почтового индекса ...

        zipOS.flush();
        zipOS.finish();
        baos.flush();
        documentBody = baos.toByteArray();
        zipOS.close();
        baos.close();

Тогда мой ответ HTTP будет

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(new MediaType("application", "zip"));
    headers.setContentLength(documentBody.length);
    headers.add("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
    ByteArrayResource resource = new ByteArrayResource(documentBody);

    return ResponseEntity.ok()
            .headers(headers)
            .body(resource);

Таким образом, я избегаю создания файла, который хорош.

Большое спасибо за помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...