今天,一位同事遇到一個編碼問題,如下
運行環(huán)境:Centos 6.* 【LANG zh_CN.GB18030】
編程語言:java
需求描述:從GBK編碼的db2數(shù)據(jù)庫中讀取數(shù)據(jù),并通過java語言生成一個UTF-8格式的XML文件,然后再通過java進(jìn)行zip壓縮;
問題描述:生成的XML文件部分中文尾部亂碼;
其實,我對java不熟,所以也到網(wǎng)上找各種資料,尋求的問題是【java GBK轉(zhuǎn)UTF8】:
有這樣的一篇回答我覺得講的蠻清晰的:
作者:溫悅
鏈接:https://www.zhihu.com/question/20361462/answer/14899233
來源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
【內(nèi)容如下】
好吧,看來問的人和回答的人都不一定清楚什么是“編碼和編碼格式”,以及如何理解“java中字符串的編碼”;
首先明確幾點:unicode是一種“編碼”,所謂編碼就是一個編號(數(shù)字)到字符的一種映射關(guān)系,就僅僅是一種一對一的映射而已,可以理解成一個很大的對應(yīng)表格GBK、UTF-8是一種“編碼格式”,是用來序列化或存儲1中提到的那個“編號(數(shù)字)”的一種“格式”;
GBK和UTF-8都是用來序列化或存儲unicode編碼的數(shù)據(jù)的,但是分別是2種不同的格式; 他們倆除了格式不一樣之外,他們所關(guān)心的unicode編碼范圍也不一樣,utf-8考慮了很多種不同國家的字符,涵蓋整個unicode碼表,所以其存儲一個字符的編碼的時候,使用的字節(jié)長度也從1字節(jié)到4字節(jié)不等;而GBK只考慮中文——在unicode中的一小部分——的字符,的編碼,所以它算好了只要2個字節(jié)就能涵蓋到絕大多數(shù)常用中文(2個字節(jié)能表示6w多種字符),所以它存儲一個字符的時候,所用的字節(jié)長度是固定的;
上述2個概念不懂的請馬上google,下面不再贅述;我下面說說這個問題本身...的問題在哪里首先java的string使用的編碼是unicode,但是,當(dāng)string存在于內(nèi)存中時(也就是當(dāng)程序運行時、你在代碼中用string類型的引用對它進(jìn)行操作時、也就是string沒有被存在文件中且也沒有在網(wǎng)絡(luò)中傳輸(序列化)時),是“只有編碼而沒有編碼格式的”,所以java程序中的任何String對象,說它是gbk還是utf-8都是錯的,gbk和utf-8是編碼格式而不是編碼,String在內(nèi)存中不需要“編碼格式”(記住編碼格式是在存文件或序列化的時候使用的), 它只是一個unicode的字符串而已所以java里面String是不帶編碼格式的,而String.toByteArray(charsetName)得到的byteArray是帶編碼格式的,格式就是你傳入的'charsetName',我們不妨把toByteArray的這個過程叫做“編碼”;另外,new String(byte[], charsetName)是把一個byte數(shù)組(帶編碼格式)以charsetName指定的編碼格式翻譯為一個不帶編碼格式的String對象,我們不妨把這個過程叫“解碼”;
最后,總結(jié)了兩種方法:
【方法1:生成UTF-8文件】
import java.nio.charset.Charset;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
public class HelloWorld {
public static void main(String[] args) {
System.out.println(Charset.defaultCharset());
try {
String nbuf = "你好"; //這是個unicode
System.out.println(nbuf); //輸出你好
FileOutputStream out = new FileOutputStream("1.txt", false);
byte[] b = nbuf.getBytes("UTF-8"); //unicode->utf-8
for (byte temp:b) {
out.write(temp);
}
out.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
【方法2:生成UTF-8文件】
import java.nio.charset.Charset;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
public class HelloWorld {
public static void main(String[] args) {
System.out.println(Charset.defaultCharset());
try {
String nbuf = "你好"; //這是個unicode
System.out.println(nbuf); //輸出你好
FileOutputStream out = new FileOutputStream("1.txt", false);
OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
osw.write(nbuf);
osw.flush();
osw.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
當(dāng)然,UTF-8轉(zhuǎn)GBK也是類似的;