Java文件編碼
處理文本文件時(shí),經(jīng)常會碰上亂碼。那么,亂碼是怎么產(chǎn)生的呢?
文件以一定的編碼規(guī)則存儲在計(jì)算機(jī)中,卻又以字符的形式顯示在屏幕上。為了能有效節(jié)省存儲空間,又提高轉(zhuǎn)化為字符的效率,人們研究出多種編碼格式。例如,utf-16,utf-8,gbk,gb18030..
大家知道,所有文件在計(jì)算機(jī)中都以二進(jìn)制的形式存在。在java中,我們自然可以選擇使用字節(jié)流來處理文件,更常用的還是字符流。
編碼原理
java的nio中,Reader是所有輸入字符流的父類,InputStream是所有輸入字節(jié)流的父類。
字符 -> 編碼 -> 字節(jié)
字節(jié) -> 解碼 -> 字符
當(dāng)我們使用utf-8進(jìn)行編碼時(shí),就必須使用utf-8解碼。

picture1
當(dāng)使用GBK編碼,iso-8859-1解碼時(shí),會出現(xiàn)以下情況:

picture2
編碼解碼的不可逆性
byte ge[] = { (byte) 0xb8, (byte) 0xf6 };
-
若使用
String s = new String(ge, "gbk");打印出s,為
個(gè)再按幾種編碼格式對 s 進(jìn)行編碼:
//則取出的字節(jié)值為:-28,-72,-86。 //‘個(gè)’的utf8編碼 s.getBytes("utf8") //得到0xb8,0xf6?!畟€(gè)’的gbk編碼 s.getBytes("gbk") -
若使用
String s = new String(ge, "utf8");此時(shí)s已經(jīng)是亂碼。
//得到-17,-65,-67,-17,-65,-67 s.getBytes("utf8")此時(shí)s的內(nèi)容已經(jīng)完全亂掉了,所以再用
s.getBytes("gbk");
得到的數(shù)據(jù)也是亂的,無法逆向出真正的內(nèi)容來。
兩種正確解析方式
采用開源庫:CpDetector進(jìn)行自動檢測文本編碼
-
使用字符流
Charset charset = codepageDetectorProxy.detectCodepage(inputStream,100); bufferedReader = new BufferedReader(new InputStreamReader(inputStream,charset.name())); while((line = bufferedReader.readLine()) != null) { contentTxt += line; } -
使用字節(jié)流
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); Charset charset = codepageDetectorProxy.detectCodepage(inputStream,100); bytes = new byte[bufferedInputStream.available()]; bufferedInputStream.read(bytes); contentTxt += Charset.forName(charset.name()).decode(ByteBuffer.wrap(bytes)).toString();
結(jié)尾
參考鏈接:
time:30min