Вопрос

Моя цель — закодировать файл и заархивировать его в папке в Java.Мне нужно использовать библиотеку кодеков Apache Commons.Я могу закодировать и заархивировать его, и он работает нормально, но когда я декодирую его обратно в исходную форму, похоже, что файл не полностью закодирован.Похоже, не хватает нескольких деталей.Может ли кто-нибудь сказать мне, почему это происходит?

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

private void zip() {
    int BUFFER_SIZE = 4096;
    byte[] buffer = new byte[BUFFER_SIZE];

    try {
        // Create the ZIP file
        String outFilename = "H:\\OUTPUT.zip";
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
                outFilename));

        // Compress the files
        for (int i : list.getSelectedIndices()) {
            System.out.println(vector.elementAt(i));
            FileInputStream in = new FileInputStream(vector.elementAt(i));
            File f = vector.elementAt(i);

            // Add ZIP entry to output stream.
            out.putNextEntry(new ZipEntry(f.getName()));

            // Transfer bytes from the file to the ZIP file
            int len;

            while ((len = in.read(buffer)) > 0) {
                buffer = org.apache.commons.codec.binary.Base64
                        .encodeBase64(buffer);
                out.write(buffer, 0, len);

            }

            // Complete the entry
            out.closeEntry();
            in.close();

        }

        // Complete the ZIP file
        out.close();
    } catch (IOException e) {
        System.out.println("caught exception");
        e.printStackTrace();
    }
}
Это было полезно?

Решение

Данные в кодировке BASE64 обычно длиннее исходных, однако вы используете длину исходных данных для записи закодированных данных в выходной поток.

Вы используете размер сгенерированного массива вместо вашей переменной. len.

Второе уведомление – не переопределять buffer каждый раз, когда вы кодируете байт.Просто запишите результат в вывод.

 while ((len = in.read(buffer)) > 0)  {                         
     byte [] enc = Base64.encodeBase64(Arrays.copyOf(buffer, len));
     out.write(enc, 0, enc.length);
 }

ОБНОВЛЯТЬ:Использовать Массивы.copyOf(...) установить длину входного буфера для кодирования.

Другие советы

Ваша главная проблема заключается в том, что кодировка Base64 не может быть приложена к блокам (особенно не реализация Apache-Commons).Эта проблема ухудшается, потому что вы даже не знаете, насколько большими его блоки являются, так как это зависит от байтов, прочитанных in.read(..).

Поэтому у вас есть две альтернативы:

  1. Загрузите полный файл в память, а затем примените кодировку Base64.
  2. Используйте альтернативную реализацию энкодера Base64, которая работает на основе потока (проект Apache Batik, по-видимому, содержит такую реализацию: org.apache.batik.util.base64EncoderStream )

Когда вы читаете содержимое файла в буфер , вы получаете len bytes.Когда BASE64 кодирует это, вы получаете больше, чем Len Bytes, но вы все равно только пишу Len Bytes в файл.Эта фасоль, что последняя часть ваших чтения будет усечена.

Кроме того, если ваш читал не заполняет весь буфер, вы не должны Base64 кодировать больше, чем Len Bytes, поскольку вы в противном случае получите трейлинг 0s в заполнении последних байтов.

Объединение информации выше этого означает, что вы должны Base64 кодировать весь файл (прочитайте все в байте []), если вы не можете гарантировать, что каждый кусок, который вы читаете, могут вписаться именно в кодированное сообщение Base64.Если ваши файлы не очень большие, я бы порекомендовал прочитать весь файл.

Меньшая проблема в том, что при чтении в вашем цикле вы, вероятно, должны проверить «> -1», а не «> 0», но int его случай это не имеет значения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top