Java基礎之IO轉換流學習
Java基礎之IO轉換流學習
簡要概述
-
作用
-
字元編碼與解碼
字元編碼(Character Encoding):就是一套自然語言的字元與二進位制數之間的對應規則。
編碼表:則是生活中文字和計算機中二進位制的對應規則。
計算機中儲存的資訊都是用二進位制數表示的,而我們在螢幕上看到的數字、英文、標點符號、漢字等字元是二進位制數轉換之後的結果。
編碼:按照某種規則,將字元儲存到計算機中(字元(能看懂的)–位元組(看不懂的))
解碼:將儲存在計算機中的二進位制數按照某種規則解析顯示出來,稱為解碼(位元組(看不懂的)–>字元(能看懂的))
// 編碼:通過指定的字符集解碼位元組陣列 byte[] -- String public String(byte bytes[], String charsetName) throws UnsupportedEncodingException { this(bytes, 0, bytes.length, charsetName); } // 解碼:使用指定的字符集合把字串編碼為位元組陣列 String -- byte[] public byte[] getBytes(String charsetName) throws UnsupportedEncodingException { if (charsetName == null) throw new NullPointerException(); return StringCoding.encode(charsetName, value, 0, value.length); }
字符集
介紹
-
概念
字符集(Charset):也叫編碼表。是一個系統支援的所有字元的集合,包括各國家文字、標點符號、圖形符號、數字等。
計算機要準確的儲存和識別各種字符集符合,需要進行字元編碼,一套字符集必然至少有一套字元編碼。常見字符集有ASCII字符集、GBK字符集、Unicode字符集等。
當指定了編碼,它對應的字符集自然就指定了。
分類
-
ASCII字符集
ASCII(American Standard Code for Information Interchange,美國資訊交換標準程式碼)是基於拉丁字母的一套電腦編碼系統,用於顯示現代英語,主要包括控制字元(Enter鍵、退格、換行鍵等)和可顯示字元(英文大小寫字元、阿拉伯數字和西文符號)。
基本的ASCII字符集,使用7位(bits)表示一個字元,共128字元。ASCII的擴充套件字符集使用8位(bits)表示一個字元,共256字元,方便支援歐洲常用字元。
-
ISO-8859-1字符集
拉丁碼錶,別名Latin-1,用於顯示歐洲使用的語言,包括荷蘭、丹麥、德語、義大利語、西班牙語等。
ISO-8859-1使用單位元組編碼,相容ASCII編碼。
-
GBxxx字符集
GB就是國標的意思,是為了顯示中文而設計的一套字符集。
GB2312:簡體中文碼錶。一個小於127的字元的意義與原來相同。但兩個大於127的字元連在一起時,就表示一個漢字,這樣大約可以組合了包含7000多個簡體漢字,此外數學符號、羅馬希臘的字母、日文的假名們都編進去了,連在ASCII裡本來就有的數字、標點、字母都統統重新編了兩個位元組長的編碼,這就是常說的"全形"字元,而原來在127號以下的那些就叫"半形"字元了。
GBK:最常用的中文碼錶。是在GB2312標準基礎上的擴充套件規範,使用了雙位元組編碼方案,共收錄了21003個漢字,完全相容GB2312標準,同時支援繁體漢字以及日韓漢字等。
GB18030:最新的中文碼錶。收錄漢字70244個,採用多位元組編碼,每個字可以由1個、2個或4個位元組組成。支援中國國內少數民族的文字,同時支援繁體漢字以及日韓漢字等。
-
Unicode字符集
Unicode編碼系統為表達任意語言的任意字元而設計,是業界的一種標準,也稱為統一碼、標準萬國碼。
它最多使用4個位元組的數字來表達每個字母、符號,或者文字。有三種編碼方案:UTF-8、UTF-16和UTF-32。最為常用的UTF-8編碼。
UTF-8編碼,可以用來表示Unicode標準中任何字元,它是電子郵件、網頁及其他儲存或傳送文字的應用中,優先採用的編碼。網際網路工程工作小組(IETF)要求所有網際網路協議都必須支援UTF-8編碼。所以,我們開發Web應用,也要使用UTF-8編碼。它使用一至四個位元組為每個字元編碼,編碼規則:
128個US-ASCII字元,只需一個位元組編碼。
拉丁文等字元,需要二個位元組編碼。
大部分常用字(含中文),使用三個位元組編碼。
其他極少使用的Unicode輔助字元,使用四位元組編碼
亂碼舉例
-
文字編碼與讀取編碼不一致
IDEA設定,都是預設的UTF-8編碼,但是,當讀取Windows系統中建立的文字檔案時,由於Windows系統的預設是GBK編碼,就會出現亂碼
/** * @Author charlesYan * @Description //測試亂碼情況:原始檔採用gbk編碼,讀取時採用utf-8解碼 * @Date 11:11 2020/11/17 * @Param [] * @return void **/ @Test public void testUnintelligible(){ try (FileReader fr = new FileReader("E:\\Blog\\202011171130.txt"); FileInputStream fis = new FileInputStream("E:\\Blog\\202011171130.txt");) { int len; while ((len = fr.read()) != -1) { System.out.println((char) len); } // 定義位元組陣列 byte[] b = new byte[1024]; // 定義長度 int length; while ((length = fis.read(b)) != -1) { System.out.println(new String(b,0,length)); } } catch (Exception e) { e.printStackTrace(); } }
轉換流
InputStreamReader類(位元組流->字元流)
-
簡介
轉換流java.io.InputStreamReader,是Reader的子類,從字面意思可以看出它是從位元組流到字元流的橋樑。它讀取位元組,並使用指定的字符集將其解碼為字元。它的字符集可以由名稱指定,也可以接受平臺的預設字符集。
-
構造方法
InputStreamReader(InputStream in): 建立一個使用預設字符集的字元流。 InputStreamReader(InputStream in, String charsetName): 建立一個指定字符集的字元流。
-
使用轉換流解決編碼問題
/** * @Author charlesYan * @Description //使用轉換流讀取資料,解決讀取亂碼問題 * @Date 14:41 2020/11/17 * @Param [] * @return void **/ @Test public void testInputStreamReader(){ // 檔案路徑內容採用gbk編碼,建立流物件指定GBK編碼 try(InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\Blog\\202011171112.txt"), "GBK");) { // 定義變數,儲存字元 int read; // 使用指定編碼字元流讀取,正常解析 while ((read = isr.read()) != -1) { System.out.println((char)read); } } catch (Exception e) { e.printStackTrace(); } }
OutputStreamWriter類(字元流->位元組流)
-
簡介
轉換流java.io.OutputStreamWriter ,是Writer的子類,字面看容易混淆會誤以為是轉為字元流,其實不然,OutputStreamWriter為從字元流到位元組流的橋樑。使用指定的字符集將字元編碼為位元組。它的字符集可以由名稱指定,也可以接受平臺的預設字符集
-
構造方法
OutputStreamWriter(OutputStream in): 建立一個使用預設字符集的字元流。 OutputStreamWriter(OutputStream in, String charsetName): 建立一個指定字符集的字元流。
-
指定編碼構造檔案
/** * @Author charlesYan * @Description //使用轉換流構造指定編碼檔案 * @Date 14:56 2020/11/17 * @Param [] * @return void **/ @Test public void testOutputStreamWriter() throws Exception { // 此時建立的檔案必須以UTF-8格式開啟,否則亂碼 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\Blog\\202011171500.txt")); String content = "你好";// 儲存為6個位元組 osw.write(content); osw.close(); // 此時建立的檔案必須以GBK格式開啟,否則亂碼 OutputStreamWriter gbkOsw = new OutputStreamWriter(new FileOutputStream("E:\\Blog\\202011171501.txt"), "GBK"); String substance = "明天";// 儲存為4個位元組 gbkOsw.write(substance); gbkOsw.close(); }
注意事項
-
提高效率
為了達到最高效率,可以考慮在 BufferedReader 內包裝 InputStreamReader
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("E:\\Blog\\202011171501.txt")));
-
FileReader類僅僅是InputStreamReader的簡單衍生並未擴充套件任何功能
-
FileReader類讀取資料實質是InputStreamReader類在讀取,而InputStreamReader讀取資料實際是StreamDecoder類讀取,因此在使用字元輸入流的時候實際是StreamDecoder類在發揮作用
參考連結
-
史上最騷最全最詳細的IO流教程,沒有之一!
https://www.cnblogs.com/yichunguo/p/11775270.html
-
JAVA基礎知識之InputStreamReader流
https://blog.csdn.net/ai_bao_zi/article/details/81133476
相關文章
- java基礎學習_io流之FileInputStreamJava
- Java基礎(八)——IO流2_緩衝流、轉換流Java
- Java基礎知識回顧之六 —– IO流Java
- Java基礎知識回顧之六 ----- IO流Java
- JAVA_基礎IO流物件流(三)Java物件
- 8、IO流:轉換流
- Java零基礎學java之IO流--05InputStream位元組輸入流Java
- Java基礎 Java-IO流 深入淺出Java
- Java IO學習筆記四:Socket基礎Java筆記
- [java IO流]之 IO概述Java
- Java基礎(八)——IO流1_位元組流、字元流Java字元
- java基礎(四):談談java中的IO流Java
- Java基礎14-java進階(5)【IO流】Java
- Java中IO流學習總結Java
- Java學習筆記09(IO流)Java筆記
- [Java基礎]之 資料型別轉換Java資料型別
- java基礎學習:JavaWeb之JSPJavaWebJS
- java基礎學習:JavaWeb之ServletJavaWebServlet
- JAVA基礎學習篇之反射Java反射
- Java學習之基礎語法Java
- Java程式設計基礎23——IO(其他流)&PropertiesJava程式設計
- IO流上:概述、字元流、緩衝區(java基礎)字元Java
- [Java基礎]IOJava
- 【重學Java】IO流Java
- Java —— 轉換流Java
- IO流(02)--屬性集、緩衝流、轉換流
- 基礎 IO (Linux學習筆記)Linux筆記
- Java學習之基礎語法練習Java
- Python基礎之IO流和序列化講解Python
- day012 IO【轉換流、列印流、序列化】
- java基礎學習:JavaWeb之request和responseJavaWeb
- java基礎學習:JavaWeb之ServletConfig與ServletContextJavaWebServletContext
- java基礎學習:JavaWeb之Cookie和SessionJavaWebCookieSession
- java基礎學習之類集框架(十)Java框架
- JAVA基礎之六-Stream(流)簡介Java
- JAVA學習--JAVA基礎(一)Java
- [java IO流]之 萬能輸出流列印流printWriterJava
- 轉行Java能學會嗎?零基礎學習Java的學習路線Java