Java讀取UTF-8格式txt檔案第一行出現亂碼——問號“?”及解決;Java讀帶有BOM的UTF-8檔案亂碼原因及解決方案

來源:互聯網
上載者:User

 Java讀取UTF-8的txt檔案第一行出現亂碼“?”及解決

test.txt檔案內容:
A中
2國
3
4
5
6

 

test.txt檔案採用寫字板儲存為UTF-8格式
儲存並關閉後使用寫字板再次開啟該UTF-8文檔,中文、字母正常顯示

 

測試代碼:

 

[java] view plaincopy

  1. import java.io.BufferedReader;  
  2. import java.io.File;  
  3. import java.io.FileInputStream;  
  4. import java.io.InputStreamReader;  
  5.   
  6. public class ReadTxtFile {  
  7.   
  8.     public static void main(String[] args) {  
  9.         try {  
  10.             String charsetName = "UTF-8";   
  11.             String path = "D:/to_delete/test.txt";  
  12.   
  13.             File file = new File(path);  
  14.             if (file.isFile() && file.exists())   
  15.             {  
  16.                 InputStreamReader insReader = new InputStreamReader(  
  17.                         new FileInputStream(file), charsetName);  
  18.   
  19.                 BufferedReader bufReader = new BufferedReader(insReader);  
  20.   
  21.                 String line = new String();  
  22.                 while ((line = bufReader.readLine()) != null) {  
  23.                     System.out.println(line);  
  24.                 }  
  25.                 bufReader.close();  
  26.                 insReader.close();  
  27.             }  
  28.   
  29.         } catch (Exception e) {  
  30.             System.out.println("讀取檔案內容操作出錯");  
  31.             e.printStackTrace();  
  32.         }  
  33.     }  
  34.   
  35. }  

 

 

程式執行結果:
?A中
2國
3
4
5
6

 

我的解決辦法:

使用UltraEdit將上邊的txt檔案另存新檔UTF-8無BOM格式;

或者

使用Notepad++開啟上邊的txt檔案執行如下操作“格式-->以UTF-8無BOM格式編碼”,修改後將txt文本進行儲存。

 

 

 

網上有篇非常好的文章,論述了問題出現的原因及解決辦法Java讀帶有BOM的UTF-8檔案亂碼原因及解決方案

 

url:http://daimojingdeyu.javaeye.com/blog/397661

 

關鍵字: java 讀utf-8, java寫utf-8, 編碼, utf-8 亂碼

最近在處理檔案時發現了同樣類型的檔案使用的編碼可能是不同的。所以想將檔案的格式統一一下(因為UTF-8的通用性,決定往UTF-8統一),遇見的第一個問題是:如何查看現有檔案的編碼方式。 

上網找了一下,找到幾篇比較好文章,這裡就不轉載啦把連結搞過來。 
檔案編碼問題集錦 
字串編碼(charset,encoding,decoding)問題原理 
Java編碼淺析 
判定檔案編碼或文字資料流編碼的方法 
上面的幾篇文章可以看成認識編碼問題的“從入門到精通” 

如果你看完了上面的文章,一定瞭解到了,在java中,class檔案採用utf8的編碼方式,JVM運行時採用utf16。Java的字串是永遠都是unicode的,採用的是UTF-16的編碼方式。 

想測試一下,java對UTF-8檔案的讀寫的能力,結果發現了一個很鬱悶的問題,如果通過java寫的UTF-8檔案,使用Java可以正確的讀,但是如果用記事本將相同的內容使用UTF-8格式儲存,則在使用程式讀取是會從檔案中多讀出一個不可見字元。 
測試代碼如下: Java代碼 

  1.   
  2. import java.io.BufferedReader;   
  3. import java.io.File;   
  4. import java.io.FileInputStream;   
  5. import java.io.IOException;   
  6. import java.io.InputStreamReader;   
  7.   
  8.   
  9. public class UTF8Test {   
  10.     public static void main(String[] args) throws IOException {   
  11.         File f  = new File("./utf.txt");   
  12.         FileInputStream in = new FileInputStream(f);   
  13.         // 指定讀取檔案時以UTF-8的格式讀取   
  14.         BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));   
  15.            
  16.         String line = br.readLine();   
  17.         while(line != null)   
  18.         {   
  19.             System.out.println(line);   
  20.             line = br.readLine();   
  21.         }   
  22.     }   
  23. }  
[java] view plaincopy

 
  1. import java.io.BufferedReader;  
  2. import java.io.File;  
  3. import java.io.FileInputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6.   
  7.   
  8. public class UTF8Test {  
  9.     public static void main(String[] args) throws IOException {  
  10.         File f  = new File("./utf.txt");  
  11.         FileInputStream in = new FileInputStream(f);  
  12.         // 指定讀取檔案時以UTF-8的格式讀取  
  13.         BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));  
  14.           
  15.         String line = br.readLine();  
  16.         while(line != null)  
  17.         {  
  18.             System.out.println(line);  
  19.             line = br.readLine();  
  20.         }  
  21.     }  
  22. }  

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 ID:4508058 
不過在我關掉的一些頁面中記得有篇檔案說這個bug只在jdk1.5及之前的版本才有,說是1.6已經解決了,從目前來看1.6隻是解決了讀取帶有BOM檔案失敗的問題,還是不能區別處理有BOM和無BOM的UTF-8編碼的檔案,從Bug ID:4508058裡的描述可以看出,這個問題將作為一個不會修改的問題關閉,對於BOM編碼的識別將由應用程式自己來處理,原因可從另處一個bug處查看到,因為Unicode對於BOM的編碼的規定可能發生變化。也就是說對於一個UTF-8的檔案,應用程式需要知道這個檔案有沒有寫BOM,然後自己決定處理BOM的方式。 

在上面的while迴圈中可加入下面的代碼,測試一下讀出內容: Java代碼 

  1. byte[] allbytes = line.getBytes("UTF-8");    
  2.             for (int i=0; i < allbytes.length; i++)   
  3.             {   
  4.                 int tmp = allbytes[i];   
  5.                 String hexString = Integer.toHexString(tmp);   
  6.                 // 1個byte變成16進位的,只需要2位就可以表示了,取後面兩位,去掉前面的符號填充   
  7.                 hexString = hexString.substring(hexString.length() -2);   
  8.                 System.out.print(hexString.toUpperCase());   
  9.                 System.out.print(" ");   
  10.             }  
[java] view plaincopy

 
  1. byte[] allbytes = line.getBytes("UTF-8");   
  2.             for (int i=0; i < allbytes.length; i++)  
  3.             {  
  4.                 int tmp = allbytes[i];  
  5.                 String hexString = Integer.toHexString(tmp);  
  6.                 // 1個byte變成16進位的,只需要2位就可以表示了,取後面兩位,去掉前面的符號填充  
  7.                 hexString = hexString.substring(hexString.length() -2);  
  8.                 System.out.print(hexString.toUpperCase());  
  9.                 System.out.print(" ");  
  10.             }  

輸出結果如下: 引用EF BB BF 54 68 69 73 20 69 73 20 74 68 65 20 66 69 72 73 74 20 6C 69 6E 65 2E 
?This is the first line. 
54 68 69 73 20 69 73 20 73 65 63 6F 6E 64 20 6C 69 6E 65 2E 
This is second line. 

紅色部分的"EF BB BF"剛好是UTF-8檔案的BOM編碼,可以看出Java在讀檔案時沒能正確處理UTF-8檔案的BOM編碼,將前3個位元組當作常值內容來處理了。 

使用連結中提供的代碼可以解決碰到的亂碼問題: 
http://koti.mbnet.fi/akini/java/unicodereader/ 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.