java.io.tem_从屌丝到架构师的飞越(IO流篇)-转换流
一.介紹
字符流=字節流+編碼集,在實際讀取的時候其實字符流還是按照字節來讀取,但是會更具編碼集進行查找編碼集字典解析相應的字節,使得一次讀取出一個字符;
轉換流就是原本是字節流,但是讀取到的數據是字符,所以我們希望使用字符流來進行操作,那么就可以使用轉換流進行轉換;
轉換流=字節流+編碼集。
轉換流的特點是可以指定編碼集。
轉換流的作用:
(1)從控制臺讀取數據輸入(鍵盤輸入),將它們寫入到文件(我們寫的是字符吧);
(2)當對文件進行解析的時候,如果涉及編碼,就需要使用轉換流進行解碼----亂碼可不好玩。
二.知識點介紹
1、System.in與Ssytem.out
2、InputStreamReader與OutputStreamWriter
3、OutputStreamWriter類
4、轉換流和子類區別
5、編碼表
三.上課視頻對應說明文檔
1、System.in與System.out
我們常見的System.in與System.out就是典型的字節流,可以直接與控制臺進行數據傳輸。
如:OutputStream os = System.out;
方法阻塞:
當調用這個方法時,程序會進行等待,當方法調用結束后,阻塞結束。
Scanner并不是鍵盤錄入,是文本掃描,可以根據綁定IO資源的不同,掃表不同的文本資源,如果給予文件,則掃描文件,如果給予System.in則掃描鍵盤錄入數據
代碼示例:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
/*
* 轉換流? 是 字符流的子類
*
* 字符流? =? 字節流? + 編碼表 .? 保證了編碼表 和 文件的編碼 一致 ,能夠讀取數據成功.
*? ? ? ? ? ? 編碼表和 文件的編碼不一致, 亂碼.
* InputStreamReader(InputStream in, String charsetName) 創建使用指定字符集的InputStreamReader。
*/
public class Demo {
public static void main(String[] args) throws IOException {
//創建? InputStreamReader 對象
InputStreamReader isr = new InputStreamReader(new FileInputStream("bj.txt"), "utf8") ;
char ch? = (char)isr.read();
System.out.println(ch);
}
}
2、InputStreamReader與OutputStreamWriter
操作字節流對于程序來說過于繁瑣,程序員更偏愛操作字符。所以,當面對一些字節流的操作時,我們可以將其轉換為字符流再進行操作,這樣便非常方便了。
(1)Reader:
InputStreamReader可以完成字節輸入流轉換為字符輸入流
(2)Writer:
OutputStreamWriter可以完成字節輸出流轉換為字符輸出流。
由上邊可以知道,轉換流是字符流的一種,創建對象時傳入對應字節流對象即可完成轉換動作。
轉換流同樣使用了包裝的思想,其構造方法接收的同樣為IO流對象,并非某個文件資源。關閉轉換流的同時即關閉了對應的字節流。
2.1、OutputStreamWriter類
查閱OutputStreamWriter的API介紹,OutputStreamWriter 是字符流通向字節流的橋梁:可使用指定的字符編碼表,將要寫入流中的字符編碼成字節。它的作用的就是,將字符串按照指定的編碼表轉成字節,在使用字節流將這些字節寫出去。
代碼示例:
public static void writeCN() throws Exception {
//創建與文件關聯的字節輸出流對象
FileOutputStream fos = new FileOutputStream("c:\\cn8.txt");
//創建可以把字符轉成字節的轉換流對象,并指定編碼
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
//調用轉換流,把文字寫出去,其實是寫到轉換流的高效區中
osw.write("你好");//寫入高效區。
osw.close();
}
OutputStreamWriter流對象,它到底如何把字符轉成字節輸出的呢?
其實在OutputStreamWriter流中維護自己的高效區,當我們調用OutputStreamWriter對象的write方法時,會拿著字符到指定的碼表中進行查詢,把查到的字符編碼值轉成字節數存放到OutputStreamWriter高效區中。然后再調用刷新功能,或者關閉流,或者高效區存滿后會把高效區中的字節數據使用字節流寫到指定的文件中。
2.2、InputStreamReader類
查閱InputStreamReader的API介紹,InputStreamReader 是字節流通向字符流的橋梁:它使用指定的字符編碼表讀取字節并將其解碼為字符。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺默認的字符集。
代碼示例:
public class InputStreamReaderDemo {
public static void main(String[] args)throws IOException {
//演示字節轉字符流的轉換流
readCN();
}
public static void readCN() throws IOException{
//創建讀取文件的字節流對象
InputStream in = new FileInputStream("c:\\cn8.txt");
//創建轉換流對象
//InputStreamReader isr = new InputStreamReader(in);這樣創建對象,會用本地默認碼表讀取,將會發生錯誤解碼的錯誤
InputStreamReader isr = new InputStreamReader(in,"utf-8");
//使用轉換流去讀字節流中的字節
int ch = 0;
while((ch = isr.read())!=-1){
System.out.println((char)ch);
}
//關閉流
isr.close();
}
}
注意:在讀取指定的編碼的文件時,一定要指定編碼格式,否則就會發生解碼錯誤,而發生亂碼現象。
3、轉換流和子類區別
發現有如下繼承關系:
Writer 字符輸出流
|- OutputStreamWriter? 轉換流(字符流—>字節流)(屬于字符輸出流, 可以指定字符編碼表,用來寫入數據到文件)
|--FileWriter 操作文件中字符輸出流,采用默認的字符編碼表
Reader 字符輸入流
|- InputStreamReader: 轉換流(字節流à字符流)(屬于字符輸入流,可以指定字符編碼表,用來從文件中讀數據)
|--FileReader操作文件中字符輸入流,采用默認的字符編碼表
父類和子類的功能有什么區別呢?
OutputStreamWriter和InputStreamReader是字符和字節的橋梁:也可以稱之為字符轉換流。字符轉換流原理:字節流+編碼表。
FileWriter和FileReader:作為子類,僅作為操作字符文件的便捷類存在。當操作的字符文件,使用的是默認編碼表時可以不用父類,而直接用子類就完成操作了,簡化了代碼。
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));//默認字符集。
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");//指定GBK字符集。
FileReader fr = new FileReader("a.txt");
這三句代碼的功能是一樣的,其中第三句最為便捷。
注意:一旦要指定其他編碼時,絕對不能用子類,必須使用字符轉換流。什么時候用子類呢?
條件:
(1)操作的是文件。
(2)使用默認編碼。
總結:
字節--->編碼表--->字符 : 看不懂的--->看的懂的。? 需要讀。輸入流。 InputStreamReader
字符--->編碼表--->字節 : 看的懂的--->看不懂的。? 需要寫。輸出流。 OutputStreamWriter
4、編碼表
4.1、編碼表概念
在轉換流或者字符串的構造方法當中,我們發現有一個參數始終沒有使用,即字符串型的編碼集名稱。
如果沒有指定該名稱,則默認為”GBK”,GBK就是編碼表的一種。
編碼表即字符與存儲數據的對應關系表,每一個字符都對應一個數字。
所以,有如下公式:
字符 = 字節 + 編碼表
4.2、常用編碼表
(1)GBK:中文環境默認碼表,中文碼表(2個字節對應一個漢字)
(2)GB2312:與GBK基本相同
(3)UTF-8:萬國碼,JavaEE項目中的通用編碼表,包含各國文字編碼(一般3個字節對應一個漢字)
(4)ISO8859-1:拉丁碼表,不包含中文,是西方較通用的碼表
(5)BIG-5:繁體字碼表
4.3、編碼表使用
亂碼:當字符與字節轉換過程中使用了不同的碼表,會造成亂碼的情況。
在字符串中:
當我們將字符串轉為對應的數字字節時,需要指定碼表,則存儲了為該字符該碼表對應的數字字節,如果使用了其他碼表重寫翻譯回字符串,則拼寫的新字符串會亂碼。
在IO中:
與字符串編碼表使用類似,當以某個碼表寫出字節數據時,又使用另外碼表展示,會出現亂碼。
總結
以上是生活随笔為你收集整理的java.io.tem_从屌丝到架构师的飞越(IO流篇)-转换流的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 转专业计算机c语言,转专业申请美国计算机
- 下一篇: idea(mac) 使用收集