由於使用位元組流操控中文時不是很方便,Java就提供了字元流來進行操控中文
實作原理:位元組流編碼表
為什麼用位元組流進行複製帶有中文的文字檔時沒有問題?
因為底層操作會自動進行位元組拼接成中文
怎麼辨識該位元組是中文呢?
漢字在儲存時,無論是UTF-8或GBK,第一個位元組都是負數用來提示
是一個系統支援的所有字符的集合,包括國家文字、標點符號、圖形符號、數字等
計算機要準確的存儲和識別各種字符集符號,就需要進行字符編碼,一套字元集必然至少有一套字元編碼
常見的字元集有ASCII字元集、GBXXX字元集、Unicode字元集等
GBK:最常用的中文碼表,是在GB2312標準基礎上的擴展規範,使用了雙字節編碼方案,共收錄了21003個漢字,完全兼容GB2312標準,同時支持繁體漢字以及日韓漢字等
GB18030:最新的中文碼表,收錄漢字70244個,採用多位元組編碼,每個字可以由1個、2個或4個位元組組成。支持中國少數民族的文字,同時支持繁體漢字以及日韓漢字等
為了表達任意語言的任意字符而設計,是業界的一個標準,也稱為統一碼、標準萬國碼;它最多使用4個位元組的數字來表達每個字母、符號,或文字。有三種編碼方案:UTF-8、UTF-16、UTF32,最常用的是UTF-8
UTF-8:可以用來表示Unicode標準中的任意字符,它是電子郵件、網頁及其他儲存或傳送文件的應用中,優先採用的編碼。網路工作小組要求所有的網際網路協定都必須支援UTF-8編碼格式。它使用一到四個位元組為每個字符編碼
128個US-ASCII字符,只需要一個位元組編碼
拉丁文等字符,需要兩個字節編碼
大部分常用字(含中文),使用三個字節編碼
其他極少使用的UniCode輔助字符,使用四個字節編碼
總結:編碼時使用那種規則,解碼就需要採用對應的規則,否則會亂碼
byte[] getBytes():使用平台預設的字元集將該String編碼為一系列字節,將結果儲存到新的位元組數組中
# byte[] getBytes(String charsetName):使用指定的字元集將String編碼為一系列字節,將結果儲存到新的位元組數組中
String(byte[]bytes):透過使用平台的預設字元集解碼指定的位元組數組來建構新的String
String(byte[]bytes,String charsetName):透過指定的字元集解碼指定的位元組數組來建構新的String
IDEA中預設的編碼格式是UTF-8
字元流抽象基底類別:
Reader:字元輸入流的抽象類別
Writer:字元輸出流的抽象類別
字元流中和編碼解碼問題相關的兩個類別:
InputStreamReader:是從位元組流到字元流的橋樑:它讀取字節,並使用指定的字元集將其解碼為字元。它使用的字元集可以由名稱指定,也可以被明確指定,或者可以接受平台的預設字元集
建構方法:
InputStreamReader( InputStream in) | 建立一個使用預設字元集的InputStreamReader。 |
InputStreamReader(InputStream in, String charsetName) | 建立一個使用命名字元集的InputStreamReader。 |
OutputStreamWruter:是從字元流到位元組流的橋樑:使用自訂的字元集將寫入的字元編碼為位元組,它使用的字元集可以由名稱指定,也可以明確指定,或可以接受平台的預設字元集
建構方法:
OutputStreamWriter(OutputStream out) | #建立一個使用預設字元編碼的OutputStreamWriter。 |
OutputStreamWriter(OutputStream out, String charsetName) | 建立一個使用命名字元集的OutputStreamWriter。 |
public class ConversionStreamDemo { public static void main(String[] args) throws IOException { //创建一个默认编码格式的InputStreamReader\OutputStreamWriter InputStreamReader ipsr = new InputStreamReader(new FileInputStream("E:\\abc.txt")); OutputStreamWriter opsw = new OutputStreamWriter(new FileOutputStream("E:\\abc.txt")); //写入数据 opsw.write("你好啊"); opsw.close(); //读数据,方式一:一次读取一个字节数据 int ch; while ((ch = ipsr.read()) != -1) { System.out.print((char) ch); } ipsr.close(); } }
方法名 | 说明 |
void write(int c) | 写一个字符 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf,int off,int len) | 写入字符数组的一部分 |
void write(String str) | 写入一个字符串 |
void write(String str,int off,int len) | 写入一个字符串的一部分 |
字符流写数据需要注意缓冲区的问题,如果想要将缓冲区的数据加载出来需要在写入方法后加上刷新方法flush();
前三个方法与字节流写入方法使用相同,这里重点介绍下面两种方式
public class OutputStreamWriterDemo { public static void main(String[] args) throws IOException { //创建一个默认编码格式的OutputStreamWriter对象 OutputStreamWriter opsw=new OutputStreamWriter(new FileOutputStream("E:\\abc.txt")); //方式一:写入一个字节 opsw.write(97); opsw.flush();//如果需要在文件中立即显示输入的数据,就需要加入刷新方法 //方式二:写入一个字符数组 char[]ch={'a','b','c','二'}; opsw.write(ch); opsw.flush();//如果需要在文件中立即显示输入的数据,就需要加入刷新方法 //方式三:写入一个字符数组的一部分 opsw.write(ch,0,2); opsw.flush();//如果需要在文件中立即显示输入的数据,就需要加入刷新方法 //方式四:写入一个字符串 opsw.write("一二三"); opsw.flush();//如果需要在文件中立即显示输入的数据,就需要加入刷新方法 //方式五:写入一个字符串的一部分 opsw.write("三四五",1,2); opsw.flush();//如果需要在文件中立即显示输入的数据,就需要加入刷新方法 } }
方法名 | 说明 |
int read() | 一次读取一个字符数据 |
int read(char[] cbuf) | 一次读取一个字符数组数据 |
public class InputStreamReadDemo { public static void main(String[] args) throws IOException { //创建一个默认编码格式的InputStreamReader InputStreamReader ipsr=new InputStreamReader(new FileInputStream("E:\\abc.txt")); //读取数据,方式一一次读取一个字符数据 int ch; while ((ch=ipsr.read())!=-1){ System.out.print((char) ch); } ipsr.close(); //方式二:一次读取一个字符数组数据 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字元流實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!