2012-03-13 4 views
5

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

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

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(); 
    } 
} 
+0

Можете ли вы предоставить несколько образцов, которые показывают, что вы положили, что вы выбрали, и что вы ожидали выйти? – Anonymoose

+0

Я не думаю, что это имеет какое-либо отношение к вашей проблеме, но ваш тест 'in.read', вероятно, должен быть' in.read (buffer)> -1', поскольку это то, что утверждает api javadoc. В javadoc не говорится, что '0' означает конец потока. http://docs.oracle.com/javase/1.4.2/docs/api/java/io/InputStream.html # read% 28byte []% 29 –

+1

Если наши сердца чисты, мы можем искоренить base64 в нашей жизни. –

ответ

3

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

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

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

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

ОБНОВЛЕНИЕ: Используйте Arrays.copyOf(...), чтобы установить длину входного буфера для кодирования.

+0

Удивительный .. !! Спасибо!! Оно работает! – dmurali

+0

HI..Now, снова я столкнулся с проблемой в кодировании-декодировании файла. Когда файл действительно маленький, он кодируется n декодированным должным образом. Но он не поддерживает более крупные файлы. Например, размер моего файла равен 7.28kb, но когда я его декодирую обратно в исходную форму, только первая половина будет правильно декодирована, а следующая половина вернет мне текст в кодировке :(Как вы думаете, это из-за размера буфера ? Я сказал, что это «byte [] encodedBuf = new byte [1024]; ' – dmurali

+0

Я предполагаю, что это зависит от того, как вы декодируете файл. Кроме того, я обнаружил еще одну проблему в коде. Длина исходного буфера не указана кодирование.Это, безусловно, вызовет проблемы, если длина исходного файла не кратна вашей длине буфера. – DRCB

0

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

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

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

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

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

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

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