今天遇到一個奇葩問題,在讀取一個TXT文件時,出現開頭多了一個問號(?)。如下圖:
莫名奇妙的多了一個。最后通過網上資料,知道在Java中,class文件采用utf8的編碼方式,JVM運行時采用utf16。Java的字符串是永遠都是unicode的,采用的是UTF-16的編碼方式。
想測試一下,java對UTF-8文件的讀寫的能力,結果發現了一個很郁悶的問題,如果通過java寫的UTF-8文件,使用Java可以正確的讀,但是如果用記事本將相同的內容使用UTF-8格式保存,則在使用程序讀取是會從文件中多讀出一個不可見字符。
測試代碼如下:
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStreamReader;
- public class UTF8Test {
- public static void main(String[] args) throws IOException {
- File f = new File("./utf.txt");
- FileInputStream in = new FileInputStream(f);
- // 指定讀取文件時以UTF-8的格式讀取
- BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
- String line = br.readLine();
- while(line != null)
- {
- System.out.println(line);
- line = br.readLine();
- }
- }
- }
utf.txt通過記事本創建,另存時使用指定utf-8編碼,其內容為:
This is the first line.
This is second line.
正常的測試結果應該是直接輸出utf.txt的文本內容。可是實際上卻輸出了下面的內容:
?This is the first line.
This is second line.
第一行多出了一個問號。
通過上面的幾篇文章應該可以想到是Java讀取BOM(Byte Order Mark)的問題,在使用UTF-8時,可以在文件的開始使用3個字節的"EF BB BF"來標識文件使用了UTF-8的編碼,當然也可以不用這個3個字節。
上面的問題應該就是因為對開頭3個字節的讀取導致的。開始不太相信這個是JDK的Bug,后來在多次試驗后,問題依然存在,就又狗狗了一下,果然找到一個如下的Bug:
不過在我關掉的一些頁面中記得有篇文件說這個bug只在jdk1.5及之前的版本才有,說是1.6已經解決了,從目前來看1.6只是解決了讀取帶有BOM文件失敗的問題,還是不能區別處理有BOM和無BOM的UTF-8編碼的文件,從Bug ID:4508058里的描述可以看出,這個問題將作為一個不會修改的問題關閉,對於BOM編碼的識別將由應用程序自己來處理,原因可從另處一個bug處查看到,因為Unicode對於BOM的編碼的規定可能發生變化。也就是說對於一個UTF-8的文件,應用程序需要知道這個文件有沒有寫BOM,然后自己決定處理BOM的方式。
解決辦法:
1.保存時,選擇
2.引用正確的讀取類,比如我用的就是:org.apache.commons.io.FileUtils.readFileToString(new File(file), encoding);
ps:貼一下讀取的工具類源碼:
1 /** 2 * 讀入文件到字串中 3 * 4 * @param file 需要讀取的文件路徑 5 * @return 讀取的文件內容,若讀入失敗,則返回空字串 6 */ 7 public static String readFileToString(String file, String encoding) 8 { 9 try 10 { 11 if (StringHelper.isEmpty(encoding)) 12 { 13 encoding = "GBK"; 14 } 15 String content = org.apache.commons.io.FileUtils.readFileToString(new File(file), encoding); 16 return content; 17 } 18 catch (IOException ex) 19 { 20 logger.error("讀取文件出錯", ex); 21 } 22 return ""; 23 }
注意兩點都要過一下,希望有用。