總結(jié):只要把握文件本來(lái)的編碼以及讀取時(shí)的編碼,亂碼問(wèn)題就不難解決。

頁(yè)面編碼URF-8,get,post提交的編碼由filter配置UTF-8,中間件如tomcat server.xml配置UTF-8,數(shù)據(jù)庫(kù)UTF-8等。

注意:Java 程序里 “字節(jié)” 到 “字符”時(shí) (編碼) 需要指定編碼格式,
如 byte[]---String需要,file,xml文件-----到j(luò)ava里的String 也需要,此時(shí)未指定編碼格式,會(huì)用默認(rèn)gbk,如果指定了編碼格式就會(huì)按照指定格式生成String字符。
如下lastE2.xml 指定了 按照UTF-8 來(lái)Reader生成字符串:
new BufferedReader(new InputStreamReader(
new FileInputStream(PyFrontServiceImpl.class.getClassLoader().
getResource("py\\lastE2.xml").toURI().getPath()),"UTF-8"));

如下  
InputSource   未指定字節(jié)生成字符的編碼格式,那么就是默認(rèn)的。
InputSource source = new InputSource(new ByteArrayInputStream(resultStr.getBytes()));
如果要指定可以增加:  source.setEncoding("UTF-8"); 該方法對(duì)字符無(wú)效,因?yàn)樽址鲃?chuàng)建時(shí)會(huì)指定編碼格式,或已經(jīng)用默認(rèn)的格式指定了。
并且,使用發(fā)現(xiàn)在tomcat下會(huì)出現(xiàn)以下錯(cuò)誤: Parse Fatal Error at line 1 column 86: Invalid byte 2 of 2-byte UTF-8 sequence.
替換為字符流就OK:
 InputSource source = new InputSource(new StringReader(utf8String));// utf8String已經(jīng)是UTF-8了,所以不用再次指定
所以,在獲取 字節(jié) 到生成 字符 過(guò)程中為了避免亂碼,我們一定要制定編碼格式,UTF-8。

JVM編碼和默認(rèn)創(chuàng)建對(duì)象時(shí)的編碼(轉(zhuǎn)):





如果在正體中文Windows中,你使用以下的程式來(lái)讀取內(nèi)含「測(cè)試」文字的檔案:
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new FileReader(args[0]));
System.out.println(reader.readLine());
reader.close();
}
}

如果該檔案是使用MS950處理,那上面的程式可以正確讀出並顯示「測(cè)試」,如果文字檔案不是MS950,那就會(huì)顯示亂碼,例如,假設(shè)是UTF-8儲(chǔ)存「測(cè)試」的文字檔案:
C:\workspace>java Main sample.txt
皜祈岫

有些API若不指定編碼,通常會(huì)使用JVM預(yù)設(shè)編碼,預(yù)設(shè)會(huì)與作業(yè)系統(tǒng)預(yù)設(shè)編碼相同,可以使用Charset.defaultCharset()取得預(yù)設(shè)編碼,在API中,有許多API若不指定編碼,就會(huì)採(cǎi)用JVM預(yù)設(shè)編碼,像是String建構(gòu)式、getBytes()方法或這邊看到的FileReader等。

為了要正確讀取文字檔案,你要使用InputStreamReader,將讀入的位元組指定編碼進(jìn)行字串轉(zhuǎn)換。例如:
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(args[0]), "UTF-8"));
System.out.println(reader.readLine());
reader.close();
}
}

在正體中文Windows中,如下執(zhí)行這個(gè)程式讀取UTF-8的文字檔案就可以正確顯示「測(cè)試」:
C:\workspace>java Main sample.txt
測(cè)試

在啟動(dòng)JVM時(shí),其實(shí)可以使用-Dfile.encoding指定JVM預(yù)設(shè)編碼,例如:
C:\workspace>java -Dfile.encoding=UTF-8 Main sample.txt
皜祈岫

這次你看到了亂碼,這是因?yàn)镾ystem.out實(shí)際上是PrintStream實(shí)例,會(huì)使用JVM預(yù)設(shè)編碼輸出文字,就上例而言,System.out使用UTF-8輸出了文字,但你的Console顯示時(shí)是使用什麼編碼呢?

程式都是正確的,問(wèn)題是出在Console,這不單是發(fā)生在Windows的Console,也常有程式設(shè)計(jì)人員指著IDE中的Console問(wèn),為什麼看到亂碼或問(wèn)號(hào),請(qǐng)改變一下你的Console顯示編碼!要不然,在程式中改變一下System.out的編碼處理:
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
System.setOut(new PrintStream(System.out, true, "Big5"));

BufferedReader reader = new BufferedReader(new FileReader(args[0]));
System.out.println(reader.readLine());
reader.close();
}
}

在這個(gè)程式中,不指定FileReader的讀取,所以會(huì)使用JVM預(yù)設(shè)編碼,而System.out會(huì)用Big5,所以讀取UTF-8文字檔案時(shí),若如下:

C:\workspace>java -Dfile.encoding=UTF-8 Main sample.txt
測(cè)試

由於指定了JVM預(yù)設(shè)編碼為UTF-8,所以程式中的FileReader會(huì)用UTF-8讀取文字檔案,而輸出至主控臺(tái)時(shí),使用Big5編碼進(jìn)行處理。

使用某些API時(shí),最好明確指定使用何種編碼,或者至少,要確認(rèn)你的JVM預(yù)設(shè)編碼到底是什麼,以及API是否使用JVM預(yù)設(shè)編碼。