2012-03-13 637 views
5

我的目標是對文件進行編碼並將其壓縮到java文件夾中。我必須使用Apache的Commons-codec庫。我能夠編碼和壓縮它,它工作正常,但是當我解碼它回到它的原始形式,它看起來像文件尚未完全編碼。看起來有幾個部分不見了。有人能告訴我爲什麼會發生這種情況嗎?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 2012-03-13 09:25:17

+0

我不認爲它與你的問題有任何關係,但是你的'in.read'測試應該是in.read(buffer)> -1',因爲這就是javadoc所說的。 javadoc沒有說'0'表示流結束。 http://docs.oracle.com/javase/1.4。2/docs/api/java/io/InputStream.html#read%28byte []%29 – 2012-03-13 09:25:23

+1

如果我們的心是純淨的,我們可以在我們的有生之年剔除base64。 – 2012-03-13 09:28:17

回答

3

BASE64編碼的數據通常比源長,然而您使用的長度要編碼的源數據寫入輸出流。

您使用生成的數組的大小而不是您的變量len

第二次通知 - 每次編碼字節時不要重新定義buffer。只需將結果寫入輸出。

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

UPDATE:使用Arrays.copyOf(...)設置用於編碼的輸入緩衝器的長度。

+0

真棒.. !!謝謝!!有用! – dmurali 2012-03-13 10:05:23

+0

嗨。現在,我再次面臨編碼解碼文件的問題。當一個文件非常小時,它就會被正確編碼。但它不支持較大的文件。例如;我的文件大小隻有7.28kb,但是當我將它解碼回原始形式時,只有前半部分被正確解碼,而下半部分將編碼文本返回給我:(你認爲這是因爲緩衝區大小?我已經指定它爲'byte [] encodedBuf = new byte [1024];' – dmurali 2012-03-14 18:58:22

+0

我想這取決於你如何解碼文件,另外我在代碼中發現了另一個問題。如果源文件的長度不是緩衝區長度的整數倍,這肯定會導致問題 – DRCB 2012-03-15 08:57:30

0

您的主要問題是,base64編碼不能應用於塊式(尤其是不是apache-commons實現)。這個問題越來越嚴重,因爲你甚至不知道你的塊有多大,因爲這取決於in.read(..)讀取的字節數。

因此,你有兩個選擇:

  1. 負載完整的文件到內存,然後應用base64編碼。
  2. 使用替代的Base64編碼器實現的作品爲基礎的流(Apache的蠟染項目似乎含有這樣的實現:org.apache.batik.util.Base64EncoderStream
0

當您將文件內容讀入緩衝區時,您將獲得len字節。當base64編碼時,你得到的字節數超過len字節,但你仍然只寫len字節到文件中。這個bean的最後一部分讀取塊將被截斷。另外,如果您的讀取沒有填充整個緩衝區,您不應該base64編碼超過len字節,否則您將在填充最後一個字節時得到0。除非你可以保證你讀的每個塊都可以完全符合base64編碼的消息,否則將上面的信息結合起來就意味着你必須對整個文件進行base64編碼(將它全部讀入一個字節[])。如果你的文件不是很大,我會推薦閱讀整個文件。

一個較小的問題是,當你在循環中讀取時,你應該檢查「> -1」,而不是「> 0」,但是在他的情況下它沒有區別。