java?使用readLine()?亂碼的解決
使用readLine() 亂碼的解決
本人在公司開發(fā)程序遇到了讀取一行亂碼
eclipse 默認(rèn)為utf-8
FileInputStream f4 = new FileInputStream(new File("F:\\bb.txt")); BufferedReader bufferedReader2 = new BufferedReader(new InputStreamReader(f4)); String readLine = bufferedReader2.readLine(); //會(huì)輸出亂碼
測試文件有兩個(gè)文本文件分別為,aa.txt (UTF-8編碼),bb.txt(GB2312編碼)兩個(gè)文件中的內(nèi)容都為一個(gè)字符 中:
前提知識(shí): utf-8中文占三個(gè)字節(jié),GB2312中文占兩個(gè)字節(jié)
測試 代碼:
public class EncodeTest { @Test public void test1() throws Exception{ FileInputStream f1 = new FileInputStream(new File("F:\\aa.txt")); byte[] b1 = new byte[f1.available()]; f1.read(b1); for(byte b : b1){ System.out.println(b); } System.out.println(new String(b1)); System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); FileInputStream f2 = new FileInputStream(new File("F:\\bb.txt")); byte[] b2 = new byte[f2.available()]; f2.read(b2); for(byte b : b2){ System.out.println(b); byte[] tb = new byte[]; String lm = new String(tb); System.out.println("當(dāng)前亂碼"+lm); byte[] lm_b = lm.getBytes(); System.out.println("-----------亂碼 start--------"); for(byte bn: lm_b){ System.out.println(bn); } System.out.println("-----------亂碼 end--------"); } System.out.println(new String(b2,"gb2312")); System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); FileInputStream f3 = new FileInputStream(new File("F:\\bb.txt")); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(f3)); String readLine2 = bufferedReader.readLine(); byte[] b3 = readLine2.getBytes("UTF-8"); for(byte b : b3){ System.out.println(b); } System.out.println(new String(b3)); System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); FileInputStream f4 = new FileInputStream(new File("F:\\bb.txt")); BufferedReader bufferedReader2 = new BufferedReader(new InputStreamReader(f4,"GB2312")); String readLine = bufferedReader2.readLine(); byte[] b4 =readLine.getBytes("UTF-8"); for(byte b : b4){ System.out.println(b); } System.out.println(new String(b4)); System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); } }
通過分析打印結(jié)果:
-28 #字節(jié)1
-72 #字節(jié)2
-83 #字節(jié)3
中 #utf-8 解碼后字符為:中,沒有出現(xiàn)亂碼
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-42 #字節(jié)1
當(dāng)前亂碼? #將 -42 按照utf-8 解碼后的字符是亂碼,然后再將亂碼按照utf-8編碼得到的字節(jié)如下
-----------亂碼 start--------
-17
-65
-67
-----------亂碼 end--------
-48 #字節(jié)2
當(dāng)前亂碼? ##將 -48 按照utf-8 解碼后的字符是亂碼,然后再將亂碼按照utf-8編碼得到的字節(jié)如下
-----------亂碼 start--------
-17
-65
-67
-----------亂碼 end--------
中 # 將 字節(jié)1: -42和字節(jié)2:-48 按照 gb2312 解碼 后為字符 中
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-17 # 這里為readline()方法沒有設(shè)置使用eclipse默認(rèn)編碼 默認(rèn)使用utf-8 (讀取bb.txt)
-65
-67
-17
-65
-67
?? # 輸出的中文為亂碼
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-28 #這里為readline()方法設(shè)置了編碼為GB2312 讀取一行文字為中 (讀取bb.txt)
-72
-83
中
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
小結(jié)一下
new BufferedReader(new InputStreamReader(f4)); 默認(rèn)用utf-8去解碼字節(jié),而bb.txt文件內(nèi)容的字符是gb2312 所以該 中 字符在磁盤中占兩個(gè)字節(jié),而utf-8編碼集中的中文占3個(gè)字節(jié),而readline()的時(shí)候發(fā)現(xiàn)是兩個(gè)字節(jié),當(dāng)前使用的又是utf-8,所以java底層就將這兩個(gè)字節(jié)單獨(dú)使用utf-8進(jìn)行了解碼, 每一個(gè)字節(jié) 使用utf-8編碼一次為 一個(gè)char字符,所以經(jīng)過utf-8將兩個(gè)字節(jié)分別解碼后的最終數(shù)據(jù)為兩個(gè)亂碼字符,
讀者可以看上面的代碼和打印的信息,兩字符個(gè)亂碼編碼后的字節(jié)分別為-17 -65 -67(紅色),和上面單獨(dú)將一個(gè)字節(jié)用utf-8 接碼后的字符再按照utf-8編碼后得到的字節(jié) -17 -65 -67(藍(lán)色)一樣,也就是說 當(dāng)字節(jié)按照utf-8 解碼時(shí)在utf-8編碼集中找不到對(duì)應(yīng)的正確的字符時(shí)就會(huì)默認(rèn)作為? 輸出,而? 對(duì)應(yīng)的utf-8 字節(jié) -17 -65 -67。所以當(dāng)找不到對(duì)應(yīng)正確的編碼字符時(shí)都會(huì)按照 -17 -65 -67 對(duì)應(yīng)的 字符 ? 輸出。
常識(shí): 當(dāng)使用 new BufferedReader(new InputStreamReader(f4),"文本源的編碼") 文本源的編碼一定要寫。這樣就不會(huì)有亂碼。
調(diào)用readLine的亂碼問題
readLine是一個(gè)很好用的方法,但是作為字符流的方法,確實(shí)會(huì)遇到各種關(guān)于編碼方面的問題。但是用字節(jié)流來處理數(shù)據(jù),比如說一個(gè)文本文件,要作按行處理的話,又會(huì)顯得很不靈活。
下面提供的是readLine字符流指定編碼方式的方法
//定義一個(gè)File對(duì)象 File someFile = new File("somefile.txt"); //輸入流 FileInputStream fis = new FileInputStream(someFile); InputStreamReader isr = new InputStreamReader(fis,"UTF-8"); //指定以UTF-8編碼讀入 BufferedReader br = new BufferedReader(isr); //輸出流 FileOutputStream fos = new FileOutputStream(someFile + ".生成的文件.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); //指定以UTF-8編碼輸出 while ((line = br.readLine()) != null) { //osw.write("write something"); osw.write(line); } //關(guān)閉IO流 br.close(); osw.close();
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis多表關(guān)聯(lián)查詢的實(shí)現(xiàn)(DEMO)
本節(jié)要實(shí)現(xiàn)的是多表關(guān)聯(lián)查詢的簡單demo。場景是根據(jù)id查詢某商品分類信息,并展示該分類下的商品列表,需要的朋友可以參考下2017-02-02Java在長字符串中查找短字符串的實(shí)現(xiàn)多種方法
這篇文章主要介紹了Java在長字符串中查找短字符串的實(shí)現(xiàn)多種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12java中 String和StringBuffer的區(qū)別實(shí)例詳解
這篇文章主要介紹了java中 String和StringBuffer的區(qū)別實(shí)例詳解的相關(guān)資料,一個(gè)小的例子,來測試String和StringBuffer在時(shí)間和空間使用上的差別,需要的朋友可以參考下2017-04-04Android studio按鈕點(diǎn)擊頁面跳轉(zhuǎn)詳細(xì)步驟
在Android應(yīng)用程序中,頁面跳轉(zhuǎn)是非常常見的操作,下面這篇文章主要給大家介紹了關(guān)于Android studio按鈕點(diǎn)擊頁面跳轉(zhuǎn)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06基于mybatis注解動(dòng)態(tài)sql中foreach工具的方法
這篇文章主要介紹了mybatis注解動(dòng)態(tài)sql中foreach工具方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11在Spring?MVC中使用@ControllerAdvice創(chuàng)建全局異常處理器的方法
在Spring?MVC中,可以使用@ControllerAdvice或@RestControllerAdvice注解來定義全局異常處理器類,并使用?@ExceptionHandler注解來定義處理特定異常的方法,本文就給大家介紹了Spring?MVC?@ControllerAdvice創(chuàng)建處理器的方法,需要的朋友可以參考下2023-08-08