Java?超詳細講解字符流
一、字符流的由來
由于使用字節(jié)流操控中文時不是很方便,Java就提供了字符流來進行操控中文
實現(xiàn)原理:字節(jié)流+編碼表
為什么用字節(jié)流進行復制帶有中文的文本文件時沒有問題?
因為底層操作會自動進行字節(jié)拼接成中文
怎樣識別該字節(jié)是中文呢?
漢字在存儲時,無論是UTF-8還是GBK,第一個字節(jié)都是負數(shù)用來提示
二、編碼表
字符集:
是一個系統(tǒng)支持的所有字符的集合,包括國家文字、標點符號、圖形符號、數(shù)字等
計算機要準確的存儲和識別各種字符集符號,就需要進行字符編碼,一套字符集必然至少有一套字符編碼
常見的字符集有ASCII字符集、GBXXX字符集、Unicode字符集等
GBK:最常用的中文碼表,是在GB2312標準基礎上的擴展規(guī)范,使用了雙字節(jié)編碼方案,共收錄了21003個漢字,完全兼容GB2312標準,同時支持繁體漢字以及日韓漢字等
GB18030:最新的中文碼表,收錄漢字70244個,采用多字節(jié)編碼,每個字可以由1個、2個或4個字節(jié)組成。支持中國少數(shù)民族的文字,同時支持繁體漢字以及日韓漢字等
Unicode字符集:
為了表達任意語言的任意字符而設計,是業(yè)界的一個標準,也稱為統(tǒng)一碼、標準萬國碼;它最多使用4個字節(jié)的數(shù)字來表達每個字母、符號,或者文字。有三種編碼方案:UTF-8、UTF-16、UTF32,最常用的是UTF-8
UTF-8:可以用來表示Unicode標準中的任意字符,它是電子郵件、網(wǎng)頁及其他存儲或傳送文件的應用中,優(yōu)先采用的編碼?;ヂ?lián)網(wǎng)工作小組要求所有的互聯(lián)網(wǎng)協(xié)議都必須支持UTF-8編碼格式。它使用一至四個字節(jié)為每個字符編碼
UTF-8編碼規(guī)則:
128個US-ASCII字符,只需要一個字節(jié)編碼
拉丁文等字符,需要兩個字節(jié)編碼
大部分常用字(含中文),使用三個字節(jié)編碼
其他極少使用的UniCode輔助字符,使用四個字節(jié)編碼
總結:編碼時使用那種規(guī)則,解碼就需要采用對應的規(guī)則,否則會亂碼
三、字符串中的編碼解碼問題
編碼方法(IDEA):
byte[] getBytes():使用平臺默認的字符集將該String編碼為一系列字節(jié),將結果存儲到新的字節(jié)數(shù)組中
byte[] getBytes(String charsetName):使用指定的字符集將該String編碼為一系列字節(jié),將結果存儲到新的字節(jié)數(shù)組中
解碼方法(IDEA):
String(byte[]bytes):通過使用平臺的默認字符集解碼指定的字節(jié)數(shù)組來構造新的String
String(byte[]bytes,String charsetName):通過指定的字符集解碼指定的字節(jié)數(shù)組來構造新的String
IDEA中默認的編碼格式是UTF-8
四、字符流的編碼解碼問題
字符流抽象基類:
Reader:字符輸入流的抽象類
Writer:字符輸出流的抽象類
字符流中和編碼解碼問題相關的兩個類:
InputStreamReader:是從字節(jié)流到字符流的橋梁:它讀取字節(jié),并使用指定的字符集將其解碼為字符。它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺的默認字符集
構造方法:
InputStreamReader(InputStream in) | 創(chuàng)建一個使用默認字符集的InputStreamReader。 |
InputStreamReader(InputStream in, String charsetName) | 創(chuàng)建一個使用命名字符集的InputStreamReader。 |
OutputStreamWruter:是從字符流到字節(jié)流的橋梁:使用自訂的字符集將寫入的字符編碼為字節(jié),它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺的默認字符集
構造方法:
OutputStreamWriter(OutputStream out) | 創(chuàng)建一個使用默認字符編碼的OutputStreamWriter。 |
OutputStreamWriter(OutputStream out, String charsetName) | 創(chuàng)建一個使用命名字符集的OutputStreamWriter。 |
public class ConversionStreamDemo { public static void main(String[] args) throws IOException { //創(chuàng)建一個默認編碼格式的InputStreamReader\OutputStreamWriter InputStreamReader ipsr = new InputStreamReader(new FileInputStream("E:\\abc.txt")); OutputStreamWriter opsw = new OutputStreamWriter(new FileOutputStream("E:\\abc.txt")); //寫入數(shù)據(jù) opsw.write("你好啊"); opsw.close(); //讀數(shù)據(jù),方式一:一次讀取一個字節(jié)數(shù)據(jù) int ch; while ((ch = ipsr.read()) != -1) { System.out.print((char) ch); } ipsr.close(); ? } }
四、字符流寫數(shù)據(jù)的五種方法
方法名 | 說明 |
void write(int c) | 寫一個字符 |
void write(char[] cbuf) | 寫入一個字符數(shù)組 |
void write(char[] cbuf,int off,int len) | 寫入字符數(shù)組的一部分 |
void write(String str) | 寫入一個字符串 |
void write(String str,int off,int len) | 寫入一個字符串的一部分 |
字符流寫數(shù)據(jù)需要注意緩沖區(qū)的問題,如果想要將緩沖區(qū)的數(shù)據(jù)加載出來需要在寫入方法后加上刷新方法flush();
前三個方法與字節(jié)流寫入方法使用相同,這里重點介紹下面兩種方式
public class OutputStreamWriterDemo { public static void main(String[] args) throws IOException { //創(chuàng)建一個默認編碼格式的OutputStreamWriter對象 OutputStreamWriter opsw=new OutputStreamWriter(new FileOutputStream("E:\\abc.txt")); //方式一:寫入一個字節(jié) opsw.write(97); opsw.flush();//如果需要在文件中立即顯示輸入的數(shù)據(jù),就需要加入刷新方法 //方式二:寫入一個字符數(shù)組 char[]ch={'a','b','c','二'}; opsw.write(ch); opsw.flush();//如果需要在文件中立即顯示輸入的數(shù)據(jù),就需要加入刷新方法 //方式三:寫入一個字符數(shù)組的一部分 opsw.write(ch,0,2); opsw.flush();//如果需要在文件中立即顯示輸入的數(shù)據(jù),就需要加入刷新方法 //方式四:寫入一個字符串 opsw.write("一二三"); opsw.flush();//如果需要在文件中立即顯示輸入的數(shù)據(jù),就需要加入刷新方法 //方式五:寫入一個字符串的一部分 opsw.write("三四五",1,2); opsw.flush();//如果需要在文件中立即顯示輸入的數(shù)據(jù),就需要加入刷新方法 } }
五、字符流讀數(shù)據(jù)的兩種方法
方法名 | 說明 |
int read() | 一次讀取一個字符數(shù)據(jù) |
int read(char[] cbuf) | 一次讀取一個字符數(shù)組數(shù)據(jù) |
public class InputStreamReadDemo { public static void main(String[] args) throws IOException { //創(chuàng)建一個默認編碼格式的InputStreamReader InputStreamReader ipsr=new InputStreamReader(new FileInputStream("E:\\abc.txt")); //讀取數(shù)據(jù),方式一一次讀取一個字符數(shù)據(jù) int ch; while ((ch=ipsr.read())!=-1){ System.out.print((char) ch); } ipsr.close(); //方式二:一次讀取一個字符數(shù)組數(shù)據(jù) char []ch=new char[1024]; int len; while ((len=ipsr.read(ch))!=-1){ System.out.print(new String(ch,0,len)); } ipsr.close(); } }
小結:如果使用默認編碼格式的話,那么字符輸入流InputStreamReader可以使用子類FileReader來替代,字符輸出流OutputStreamWriter可以使用其子類FileWriter來替代,兩者在使用默認編碼格式的情況下作用一致。
到此這篇關于Java 超詳細講解字符流的文章就介紹到這了,更多相關Java 字符流內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
一次"java:程序包org.aspectj.lang不存在"問題解決實戰(zhàn)記錄
這篇文章主要給大家介紹了一次"java:程序包org.aspectj.lang不存在"問題解決的實戰(zhàn)過程,這個錯誤提示意味著你的Java程序中引用了org.aspectj.lang這個包,但是該包并不存在,文章通過圖文介紹的非常詳細,需要的朋友可以參考下2023-06-06springboot整合mybatis實現(xiàn)數(shù)據(jù)庫的更新批處理方式
這篇文章主要介紹了springboot整合mybatis實現(xiàn)數(shù)據(jù)庫的更新批處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03mybatis返回list<Integer>時resultType寫Integer問題
這篇文章主要介紹了mybatis返回list<Integer>時resultType寫Integer問題,具有很好的參考價值,希望對大家有所幫助,2023-12-12Spring?BeanFactory?與?FactoryBean?的區(qū)別詳情
這篇文章主要介紹了Spring?BeanFactory?與?FactoryBean?的區(qū)別詳情,BeanFactory?和?FactoryBean?的區(qū)別卻是一個很重要的知識點,在本文中將結合源碼進行分析講解,需要的小伙伴可以參考一下2022-05-05