java压缩zip文件中文乱码问题
生活随笔
收集整理的這篇文章主要介紹了
java压缩zip文件中文乱码问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
--轉自:http://riching.iteye.com/blog/579634
用java來打包文件生成壓縮文件,有兩個地方會出現亂碼
1、內容的中文亂碼問題,這個問題網上很多人給出了解決方法,兩種:修改sun的源碼;使用開源的類庫org.apache.tools.zip.ZipOutputStream和org.apache.tools.zip.ZipEntry,這兩個類ant.jar中有,可以下載使用即可,毫無疑問,選擇后者更方便
2、壓縮文件注釋的中文亂碼問題:zos.setComment("中文測試");這個問題在網上查了半天沒看到有人解釋,遂只能自己想辦法解決。在自己機器上的工程創建的測試類,沒有任何問題,但是在公司的項目中使用一直出現亂碼,通過使用設置編碼的方法(zos.setEncoding("gbk");)終于發現了問題,測試項目的編碼方式為gbk,而公司項目的默認編碼是utf-8,所以測試項目沒問題而公司的項目中出現了問題。
org.apache.tools.zip.ZipOutputStream默認使用項目的編碼方式,理論上講utf-8也是支持中文的,是在想不通為啥還是亂碼,通過setEncoding方法改成gbk即可解決
附上一段壓縮文件的代碼
Java代碼 ?package?com.compress;?? ?? import?java.io.BufferedInputStream;?? import?java.io.BufferedOutputStream;?? import?java.io.DataInputStream;?? import?java.io.File;?? import?java.io.FileInputStream;?? import?java.io.FileOutputStream;?? ?? import?org.apache.tools.zip.ZipEntry;?? import?org.apache.tools.zip.ZipOutputStream;?? ?? public?class?CompressEncodingTest?{?? ?? ????/**? ?????*?@param?args? ?????*?@throws?Exception? ?????*/?? ????public?static?void?main(String[]?args)?throws?Exception?{?? ????????File?f?=?new?File("中文測試.txt");?? ????????ZipOutputStream?zos?=?new?ZipOutputStream(new?BufferedOutputStream(?? ????????????????new?FileOutputStream("zipTest.zip"),?1024));?? ????????zos.putNextEntry(new?ZipEntry("中國人.txt"));?? ????????DataInputStream?dis?=?new?DataInputStream(new?BufferedInputStream(?? ????????????????new?FileInputStream(f)));?? ????????zos.putNextEntry(new?ZipEntry(f.getName()));?? ????????int?c;?? ????????while?((c?=?dis.read())?!=?-1)?{?? ????????????zos.write(c);?? ????????}?? ?? ????????zos.setEncoding("gbk");?? ????????zos.setComment("中文測試");?? ?? ????????zos.closeEntry();?? ????????zos.close();?? ????}?? ?? }??
分享到:
window 修改ip腳本 | 轉:java中四種操作xml方式的比較
dabing69221 寫道 樓主說“測試項目的編碼方式為gbk,而公司項目的默認編碼是utf-8,所以測試項目沒問題而公司的項目中出現了問題 ”樓主這么分析也對,但是不全面,下面我給樓主分析一下出錯原因:
通過org.apache.tools.zip.ZipOutputStream類的源碼,我們看到這么一個方法,沒錯下面這個方法就是幕后真兇:
??? protected byte[] getBytes(String name)
??????? throws ZipException
??? {
??????? if(encoding == null)
??????????? return name.getBytes();
??????? return name.getBytes(encoding);
??????? UnsupportedEncodingException uee;
??????? uee;
??????? throw new ZipException(uee.getMessage());
??? }
以上這句代碼,就是將我們的文件名的字符變為字節,(這里變為字節的目的就是為了通過字節流把字節寫出去) 這里判斷了一下encoding是否為空,樓主如果不寫encoding的話,就會執行name.getByte()也就是使用平臺的默認字符集將此 String 編碼為 byte 序列,并將結果存儲到一個新的 byte 數組中。(這里使用平臺的默認字符集就是樓主所在項目的編碼),假如說這里項目所在編碼為UTF-8,那么這里就會自動將文件名的字符轉換為UTF-8的字節,然后寫入到底層輸出流。
當我們雙擊打開那個壓縮的zip文件時,程序就會使用ANSI編碼(通常指的是平臺的默認編碼,例如英文操作系統中是ISO-8859-1,中文系統是GBK)。別忘了,我們寫文件的時候使用UTF-8的編碼來寫文件名的,這個時候-- 奇跡出現了“亂碼”,為什么呢? GBK每個漢字占2個字節,而UTF-8每個漢字占3個字節,它們所占字節數都不一樣,亂碼是必須的,這下樓主知道為什么你的程序老是亂碼了嗎? 呵呵呵
呵呵
5 樓 riching 2013-12-02?? 引用 大神你牛逼,受教了,我這種不求甚解的習慣要改,謝謝
dabing69221 寫道 樓主說“測試項目的編碼方式為gbk,而公司項目的默認編碼是utf-8,所以測試項目沒問題而公司的項目中出現了問題 ”樓主這么分析也對,但是不全面,下面我給樓主分析一下出錯原因:
通過org.apache.tools.zip.ZipOutputStream類的源碼,我們看到這么一個方法,沒錯下面這個方法就是幕后真兇:
??? protected byte[] getBytes(String name)
??????? throws ZipException
??? {
??????? if(encoding == null)
??????????? return name.getBytes();
??????? return name.getBytes(encoding);
??????? UnsupportedEncodingException uee;
??????? uee;
??????? throw new ZipException(uee.getMessage());
??? }
以上這句代碼,就是將我們的文件名的字符變為字節,(這里變為字節的目的就是為了通過字節流把字節寫出去) 這里判斷了一下encoding是否為空,樓主如果不寫encoding的話,就會執行name.getByte()也就是使用平臺的默認字符集將此 String 編碼為 byte 序列,并將結果存儲到一個新的 byte 數組中。(這里使用平臺的默認字符集就是樓主所在項目的編碼),假如說這里項目所在編碼為UTF-8,那么這里就會自動將文件名的字符轉換為UTF-8的字節,然后寫入到底層輸出流。
當我們雙擊打開那個壓縮的zip文件時,程序就會使用ANSI編碼(通常指的是平臺的默認編碼,例如英文操作系統中是ISO-8859-1,中文系統是GBK)。別忘了,我們寫文件的時候使用UTF-8的編碼來寫文件名的,這個時候-- 奇跡出現了“亂碼”,為什么呢? GBK每個漢字占2個字節,而UTF-8每個漢字占3個字節,它們所占字節數都不一樣,亂碼是必須的,這下樓主知道為什么你的程序老是亂碼了嗎? 呵呵呵
4 樓 dabing69221 2013-12-01?? 引用 樓主說“測試項目的編碼方式為gbk,而公司項目的默認編碼是utf-8,所以測試項目沒問題而公司的項目中出現了問題 ”樓主這么分析也對,但是不全面,下面我給樓主分析一下出錯原因:
通過org.apache.tools.zip.ZipOutputStream類的源碼,我們看到這么一個方法,沒錯下面這個方法就是幕后真兇:
??? protected byte[] getBytes(String name)
??????? throws ZipException
??? {
??????? if(encoding == null)
??????????? return name.getBytes();
??????? return name.getBytes(encoding);
??????? UnsupportedEncodingException uee;
??????? uee;
??????? throw new ZipException(uee.getMessage());
??? }
以上這句代碼,就是將我們的文件名的字符變為字節,(這里變為字節的目的就是為了通過字節流把字節寫出去) 這里判斷了一下encoding是否為空,樓主如果不寫encoding的話,就會執行name.getByte()也就是使用平臺的默認字符集將此 String 編碼為 byte 序列,并將結果存儲到一個新的 byte 數組中。(這里使用平臺的默認字符集就是樓主所在項目的編碼),假如說這里項目所在編碼為UTF-8,那么這里就會自動將文件名的字符轉換為UTF-8的字節,然后寫入到底層輸出流。
當我們雙擊打開那個壓縮的zip文件時,程序就會使用ANSI編碼(通常指的是平臺的默認編碼,例如英文操作系統中是ISO-8859-1,中文系統是GBK)。別忘了,我們寫文件的時候使用UTF-8的編碼來寫文件名的,這個時候-- 奇跡出現了“亂碼”,為什么呢? GBK每個漢字占2個字節,而UTF-8每個漢字占3個字節,它們所占字節數都不一樣,亂碼是必須的,這下樓主知道為什么你的程序老是亂碼了嗎? 呵呵呵 3 樓 dabing69221 2013-12-01?? 引用 樓主,我給你分析一下,你的壓縮zip包為什么會亂碼?
分析原因:
? 我們在使用JDK自帶的ZipOutputStream壓縮文件時,壓縮文件沒有采用英文命名時,沒有問題。如果采用中文命令就會出現問題,為什么會這樣呢?我們來看看ZipOutputStream源碼,它到底是怎么把文件名轉換為字節的?
? private static byte[] getUTF8Bytes(String s)
??? {
??????? char ac[] = s.toCharArray();
??????? int i = ac.length;
??????? int j = 0;
??????? for(int k = 0; k < i; k++)
??????? {
??????????? char c = ac[k];
??????????? if(c <= '\177')
??????????? {
??????????????? j++;
??????????????? continue;
??????????? }
??????????? if(c <= '\u07FF')
??????????????? j += 2;
??????????? else
??????????????? j += 3;
??????? }
??????? byte abyte0[] = new byte[j];
??????? int l = 0;
??????? for(int i1 = 0; i1 < i; i1++)
??????? {
??????????? char c1 = ac[i1];
??????????? if(c1 <= '\177')
??????????? {
??????????????? abyte0[l++] = (byte)c1;
??????????????? continue;
??????????? }
??????????? if(c1 <= '\u07FF')
??????????? {
??????????????? abyte0[l++] = (byte)(c1 >> 6 | 192);
??????????????? abyte0[l++] = (byte)(c1 & 63 | 128);
??????????? } else
??????????? {
??????????????? abyte0[l++] = (byte)(c1 >> 12 | 224);
??????????????? abyte0[l++] = (byte)(c1 >> 6 & 63 | 128);
??????????????? abyte0[l++] = (byte)(c1 & 63 | 128);
??????????? }
??????? }
??????? return abyte0;
??? }
以上這個方法就是JDK自帶的ZipOutputStream類中將文件名裝換為字節的方法,通過源碼我們不難看出,它是先將String變為char[]數組,然后通過遍歷char[]數組,最后將char強轉為byte,存放到byte數組中。
? 如果這樣做的話,就暴露了一個問題,就是樓主所說的“中文亂碼”問題,為什么呢? 因為在Java中,一個char是2個字節(byte),而一個中文漢字是一個字符,也就是2個字節;英文字母是一個字節,所以,一個英文字母可以保存到 一個字節(byte)中,而一個中文漢字不能(道理很簡單啊,一個漢字是2個字節) --- 所以說這就是為什么保存英文的文件名是不會亂碼,但是保存中文的文件名時會亂碼的原因。
2 樓 riching 2010-06-06?? 引用 xiaohahaa 寫道 不使用外部包,只用jdk內部的類,能不能實現?
能實現,不過中文的文件名和中文的注釋(comment)會亂碼,內容沒問題 1 樓 xiaohahaa 2010-06-05?? 引用 不使用外部包,只用jdk內部的類,能不能實現?
用java來打包文件生成壓縮文件,有兩個地方會出現亂碼
1、內容的中文亂碼問題,這個問題網上很多人給出了解決方法,兩種:修改sun的源碼;使用開源的類庫org.apache.tools.zip.ZipOutputStream和org.apache.tools.zip.ZipEntry,這兩個類ant.jar中有,可以下載使用即可,毫無疑問,選擇后者更方便
2、壓縮文件注釋的中文亂碼問題:zos.setComment("中文測試");這個問題在網上查了半天沒看到有人解釋,遂只能自己想辦法解決。在自己機器上的工程創建的測試類,沒有任何問題,但是在公司的項目中使用一直出現亂碼,通過使用設置編碼的方法(zos.setEncoding("gbk");)終于發現了問題,測試項目的編碼方式為gbk,而公司項目的默認編碼是utf-8,所以測試項目沒問題而公司的項目中出現了問題。
org.apache.tools.zip.ZipOutputStream默認使用項目的編碼方式,理論上講utf-8也是支持中文的,是在想不通為啥還是亂碼,通過setEncoding方法改成gbk即可解決
附上一段壓縮文件的代碼
Java代碼 ?
- 2010-01-25 21:27
- 瀏覽 6461
- 評論(6)
- 論壇回復 / 瀏覽 (2 / 7976)
- 收藏
- 分類:編程語言
- 相關推薦
評論
6 樓 dabing69221 2013-12-23?? 引用 riching 寫道 大神你牛逼,受教了,我這種不求甚解的習慣要改,謝謝dabing69221 寫道 樓主說“測試項目的編碼方式為gbk,而公司項目的默認編碼是utf-8,所以測試項目沒問題而公司的項目中出現了問題 ”樓主這么分析也對,但是不全面,下面我給樓主分析一下出錯原因:
通過org.apache.tools.zip.ZipOutputStream類的源碼,我們看到這么一個方法,沒錯下面這個方法就是幕后真兇:
??? protected byte[] getBytes(String name)
??????? throws ZipException
??? {
??????? if(encoding == null)
??????????? return name.getBytes();
??????? return name.getBytes(encoding);
??????? UnsupportedEncodingException uee;
??????? uee;
??????? throw new ZipException(uee.getMessage());
??? }
以上這句代碼,就是將我們的文件名的字符變為字節,(這里變為字節的目的就是為了通過字節流把字節寫出去) 這里判斷了一下encoding是否為空,樓主如果不寫encoding的話,就會執行name.getByte()也就是使用平臺的默認字符集將此 String 編碼為 byte 序列,并將結果存儲到一個新的 byte 數組中。(這里使用平臺的默認字符集就是樓主所在項目的編碼),假如說這里項目所在編碼為UTF-8,那么這里就會自動將文件名的字符轉換為UTF-8的字節,然后寫入到底層輸出流。
當我們雙擊打開那個壓縮的zip文件時,程序就會使用ANSI編碼(通常指的是平臺的默認編碼,例如英文操作系統中是ISO-8859-1,中文系統是GBK)。別忘了,我們寫文件的時候使用UTF-8的編碼來寫文件名的,這個時候-- 奇跡出現了“亂碼”,為什么呢? GBK每個漢字占2個字節,而UTF-8每個漢字占3個字節,它們所占字節數都不一樣,亂碼是必須的,這下樓主知道為什么你的程序老是亂碼了嗎? 呵呵呵
呵呵
5 樓 riching 2013-12-02?? 引用 大神你牛逼,受教了,我這種不求甚解的習慣要改,謝謝
dabing69221 寫道 樓主說“測試項目的編碼方式為gbk,而公司項目的默認編碼是utf-8,所以測試項目沒問題而公司的項目中出現了問題 ”樓主這么分析也對,但是不全面,下面我給樓主分析一下出錯原因:
通過org.apache.tools.zip.ZipOutputStream類的源碼,我們看到這么一個方法,沒錯下面這個方法就是幕后真兇:
??? protected byte[] getBytes(String name)
??????? throws ZipException
??? {
??????? if(encoding == null)
??????????? return name.getBytes();
??????? return name.getBytes(encoding);
??????? UnsupportedEncodingException uee;
??????? uee;
??????? throw new ZipException(uee.getMessage());
??? }
以上這句代碼,就是將我們的文件名的字符變為字節,(這里變為字節的目的就是為了通過字節流把字節寫出去) 這里判斷了一下encoding是否為空,樓主如果不寫encoding的話,就會執行name.getByte()也就是使用平臺的默認字符集將此 String 編碼為 byte 序列,并將結果存儲到一個新的 byte 數組中。(這里使用平臺的默認字符集就是樓主所在項目的編碼),假如說這里項目所在編碼為UTF-8,那么這里就會自動將文件名的字符轉換為UTF-8的字節,然后寫入到底層輸出流。
當我們雙擊打開那個壓縮的zip文件時,程序就會使用ANSI編碼(通常指的是平臺的默認編碼,例如英文操作系統中是ISO-8859-1,中文系統是GBK)。別忘了,我們寫文件的時候使用UTF-8的編碼來寫文件名的,這個時候-- 奇跡出現了“亂碼”,為什么呢? GBK每個漢字占2個字節,而UTF-8每個漢字占3個字節,它們所占字節數都不一樣,亂碼是必須的,這下樓主知道為什么你的程序老是亂碼了嗎? 呵呵呵
4 樓 dabing69221 2013-12-01?? 引用 樓主說“測試項目的編碼方式為gbk,而公司項目的默認編碼是utf-8,所以測試項目沒問題而公司的項目中出現了問題 ”樓主這么分析也對,但是不全面,下面我給樓主分析一下出錯原因:
通過org.apache.tools.zip.ZipOutputStream類的源碼,我們看到這么一個方法,沒錯下面這個方法就是幕后真兇:
??? protected byte[] getBytes(String name)
??????? throws ZipException
??? {
??????? if(encoding == null)
??????????? return name.getBytes();
??????? return name.getBytes(encoding);
??????? UnsupportedEncodingException uee;
??????? uee;
??????? throw new ZipException(uee.getMessage());
??? }
以上這句代碼,就是將我們的文件名的字符變為字節,(這里變為字節的目的就是為了通過字節流把字節寫出去) 這里判斷了一下encoding是否為空,樓主如果不寫encoding的話,就會執行name.getByte()也就是使用平臺的默認字符集將此 String 編碼為 byte 序列,并將結果存儲到一個新的 byte 數組中。(這里使用平臺的默認字符集就是樓主所在項目的編碼),假如說這里項目所在編碼為UTF-8,那么這里就會自動將文件名的字符轉換為UTF-8的字節,然后寫入到底層輸出流。
當我們雙擊打開那個壓縮的zip文件時,程序就會使用ANSI編碼(通常指的是平臺的默認編碼,例如英文操作系統中是ISO-8859-1,中文系統是GBK)。別忘了,我們寫文件的時候使用UTF-8的編碼來寫文件名的,這個時候-- 奇跡出現了“亂碼”,為什么呢? GBK每個漢字占2個字節,而UTF-8每個漢字占3個字節,它們所占字節數都不一樣,亂碼是必須的,這下樓主知道為什么你的程序老是亂碼了嗎? 呵呵呵 3 樓 dabing69221 2013-12-01?? 引用 樓主,我給你分析一下,你的壓縮zip包為什么會亂碼?
分析原因:
? 我們在使用JDK自帶的ZipOutputStream壓縮文件時,壓縮文件沒有采用英文命名時,沒有問題。如果采用中文命令就會出現問題,為什么會這樣呢?我們來看看ZipOutputStream源碼,它到底是怎么把文件名轉換為字節的?
? private static byte[] getUTF8Bytes(String s)
??? {
??????? char ac[] = s.toCharArray();
??????? int i = ac.length;
??????? int j = 0;
??????? for(int k = 0; k < i; k++)
??????? {
??????????? char c = ac[k];
??????????? if(c <= '\177')
??????????? {
??????????????? j++;
??????????????? continue;
??????????? }
??????????? if(c <= '\u07FF')
??????????????? j += 2;
??????????? else
??????????????? j += 3;
??????? }
??????? byte abyte0[] = new byte[j];
??????? int l = 0;
??????? for(int i1 = 0; i1 < i; i1++)
??????? {
??????????? char c1 = ac[i1];
??????????? if(c1 <= '\177')
??????????? {
??????????????? abyte0[l++] = (byte)c1;
??????????????? continue;
??????????? }
??????????? if(c1 <= '\u07FF')
??????????? {
??????????????? abyte0[l++] = (byte)(c1 >> 6 | 192);
??????????????? abyte0[l++] = (byte)(c1 & 63 | 128);
??????????? } else
??????????? {
??????????????? abyte0[l++] = (byte)(c1 >> 12 | 224);
??????????????? abyte0[l++] = (byte)(c1 >> 6 & 63 | 128);
??????????????? abyte0[l++] = (byte)(c1 & 63 | 128);
??????????? }
??????? }
??????? return abyte0;
??? }
以上這個方法就是JDK自帶的ZipOutputStream類中將文件名裝換為字節的方法,通過源碼我們不難看出,它是先將String變為char[]數組,然后通過遍歷char[]數組,最后將char強轉為byte,存放到byte數組中。
? 如果這樣做的話,就暴露了一個問題,就是樓主所說的“中文亂碼”問題,為什么呢? 因為在Java中,一個char是2個字節(byte),而一個中文漢字是一個字符,也就是2個字節;英文字母是一個字節,所以,一個英文字母可以保存到 一個字節(byte)中,而一個中文漢字不能(道理很簡單啊,一個漢字是2個字節) --- 所以說這就是為什么保存英文的文件名是不會亂碼,但是保存中文的文件名時會亂碼的原因。
2 樓 riching 2010-06-06?? 引用 xiaohahaa 寫道 不使用外部包,只用jdk內部的類,能不能實現?
能實現,不過中文的文件名和中文的注釋(comment)會亂碼,內容沒問題 1 樓 xiaohahaa 2010-06-05?? 引用 不使用外部包,只用jdk內部的類,能不能實現?
總結
以上是生活随笔為你收集整理的java压缩zip文件中文乱码问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 天才编程少女16岁获哈佛offer,全民
- 下一篇: 利用营销工具,这家企业从按经验办事的老中