詳解字節(jié)流和字符流

一、明確字符和字節(jié)的概念

字節(jié):1 byte = 8 bit
字符:1 char = 2 byte = 16 bit(java默認(rèn))

在計(jì)算機(jī)硬件層面吼肥,1 bit 是數(shù)據(jù)最小的單位。但是在大多數(shù)情況下,1 bit 存儲(chǔ)的信息太少,我們通常把 1 字節(jié)作為數(shù)據(jù)最小的基本單位杖挣。

而字符實(shí)際上也是對字節(jié)的一種包裝肩榕,那為什么還需要引入字符刚陡?
對于西方世界,使用英語等語種的國家來說株汉,1字節(jié)有 256個(gè)符號編碼筐乳,對于26個(gè)英文字母加上常用的標(biāo)點(diǎn)符號已經(jīng)夠用了。這就是常用的ASCII 碼乔妈。
但是對于東方國家蝙云,中文,日文等文字路召,數(shù)量太多勃刨,1個(gè)字節(jié)根本沒有辦法表示所有的字符,所以引入了Unicode —— 統(tǒng)一編碼股淡,而這種編碼的常規(guī)字符集就是使用2個(gè)字節(jié)身隐,所以引入了字符的概念。

但是唯灵,從根本而言贾铝,一切都是字節(jié)流,字符流也是字節(jié)流的一種形式。

二垢揩、關(guān)于 java中字節(jié)流和字符流

2.1 字節(jié)流玖绿,字符流概念

Java中,讀取數(shù)據(jù)時(shí)叁巨,字節(jié)流的數(shù)據(jù)存儲(chǔ)單位是字節(jié)斑匪,會(huì)使用字節(jié)類型數(shù)組 byte[] 來保存數(shù)據(jù),可以操作字節(jié)锋勺,字節(jié)數(shù)組秤标。
而 字符流的存儲(chǔ)單位是字符,使用字符類數(shù)組 char[] 來保存數(shù)據(jù)宙刘,可以操作字符苍姜,字符數(shù)組或字符串。

2.2 java中的字節(jié)流悬包,字符流相關(guān)API

Java 的I/O庫有兩個(gè)分支:

  • 面向字節(jié)流的InputSteam和OutputStream
  • 面向字符的Reader 和 wirter
InputStream

ByteArrayInputStream:把內(nèi)存中的一個(gè)緩沖區(qū)作為 InputStream 使用 .
StringBufferInputStream: 把一個(gè) String 對象作為 InputStream .
FileInputStream:把一個(gè)文件作為 InputStream 衙猪,實(shí)現(xiàn)對文件的讀取操作
PipedInputStream :實(shí)現(xiàn)了 pipe 的概念,主要在線程中使用 . 管道輸入流是指一個(gè)通訊管道的接收端布近。
一個(gè)線程通過管道輸出流發(fā)送數(shù)據(jù)垫释,而另一個(gè)線程通過管道輸入流讀取數(shù)據(jù),這樣可實(shí)現(xiàn)兩個(gè)線程間的通訊撑瞧。
SequenceInputStream :把多個(gè) InputStream 合并為一個(gè) InputStream . “序列輸入流”類允許應(yīng)用程序把幾個(gè)輸入流連續(xù)地合并起來棵譬,
并且使它們像單個(gè)輸入流一樣出現(xiàn)。每個(gè)輸入流依次被讀取预伺,直到到達(dá)該流的末尾订咸。

OutputStream

ByteArrayOutputStream : 把信息存入內(nèi)存中的一個(gè)緩沖區(qū)中 . 該類實(shí)現(xiàn)一個(gè)以字節(jié)數(shù)組形式寫入數(shù)據(jù)的輸出流。
FileOutputStream: 文件輸出流是向 File 或 FileDescriptor 輸出數(shù)據(jù)的一個(gè)輸出流酬诀。
PipedOutputStream: 管道輸出流是指一個(gè)通訊管道的發(fā)送端脏嚷。 一個(gè)線程通過管道輸出流發(fā)送數(shù)據(jù),
而另一個(gè)線程通過管道輸入流讀取數(shù)據(jù)瞒御,這樣可實(shí)現(xiàn)兩個(gè)線程間的通訊父叙。

Reader

CharArrayReader :與 ByteArrayInputStream 對應(yīng)此類實(shí)現(xiàn)一個(gè)可用作字符輸入流的字符緩沖區(qū)
StringReader : 與 StringBufferInputStream 對應(yīng)其源為一個(gè)字符串的字符流。
FileReader : 與 FileInputStream 對應(yīng)
PipedReader :與 PipedInputStream 對應(yīng)

Writer

CharArrayWrite : 與 ByteArrayOutputStream 對應(yīng)
StringWrite :無與之對應(yīng)的以字節(jié)為導(dǎo)向的 stream
FileWrite : 與 FileOutputStream 對應(yīng)
PipedWrite :與 PipedOutputStream 對應(yīng)

2.3 字符流肴裙,字節(jié)流API的使用

字節(jié)流示例

//字節(jié)流寫文件
public static void writeFile(){
    String str = "采用數(shù)據(jù)流方式(字節(jié)流)寫文件趾唱!";
    try{
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D://hello.txt",true));
        //需要轉(zhuǎn)化為字節(jié)
        byte[] data = str.getBytes();
        bos.write(data);
        bos.close();
    }catch (FileNotFoundException e){
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
//字節(jié)流讀文件
public static void readFile(){
    try {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D://hello.txt"));
        byte[] data = new byte[1024];
        int n = -1;
        while((n=bis.read(data,0,data.length))!=-1){
            String str = new String(data,0,n,"UTF-8");
            System.out.println(str);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

字符流示例

//字符流寫文件
public static void writeFile(){
    File file = new File("D:\\hello.txt");
    String str = " hello, everybody! welcome to the study of Java!";
    try{
        FileWriter fw = new FileWriter(file);
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write(str);
        bw.close();
        fw.close();
    }catch(IOException e){
        e.printStackTrace();
    }
}
//字符流讀文件
public static void readerFile(){
    File file = new File("D:\\hello.txt");
    try{
        BufferedReader br = new BufferedReader(new FileReader(file));

        String str = null;
        while( (str = br.readLine()) != null){
            System.out.println(str);
        }
        br.close();
    }catch(FileNotFoundException e){
        e.printStackTrace();
    }catch(IOException e){
        e.printStackTrace();
    }
}

三、字節(jié)流和字符流的區(qū)別

字節(jié)流和字符流的區(qū)別:

  • 字節(jié)流在操作文件時(shí)蜻懦,本身不會(huì)用到緩沖區(qū)(內(nèi)存)甜癞,是對文件本身直接操作的;而字符流在操作時(shí)是使用到緩沖區(qū)的阻肩。
  • 字節(jié)流在操作文件時(shí)带欢,即使不關(guān)閉資源(close)文件也能輸出运授;字符流如果不是用close方法的話,則不會(huì)輸出任何內(nèi)容乔煞,說明字符流使用了緩沖區(qū)吁朦。且可以使用flush方法強(qiáng)制進(jìn)行刷新緩沖區(qū),此時(shí)在不close情況下也能輸出內(nèi)容渡贾。
  • Reader類的read()方法返回類型是int逗宜,占兩個(gè)字節(jié),如果到達(dá)流的末尾空骚,則返回-1纺讲;inputStream的read()方法雖然也返回int,打算面向字節(jié)流囤屹,占一個(gè)字節(jié)熬甚。因此對于超過一個(gè)字節(jié)的只能使用字符流來讀取,如漢字肋坚。
  • 處理方式不同乡括;字節(jié)流:處理字節(jié)和字節(jié)數(shù)組成的二進(jìn)制對象。
    字符流:處理字符智厌,字符數(shù)或字符串诲泌。

注:緩沖區(qū)是什么?铣鹏?
緩沖區(qū)可以理解為一段特殊的內(nèi)存敷扫。
在某些情況下秽澳,如果程序頻繁操作一個(gè)資源颂龙,則性能會(huì)很低,為了提升性能涂臣,可以將這部分?jǐn)?shù)據(jù)暫時(shí)讀入內(nèi)存的一塊區(qū)域惨险,之后就可以直接從內(nèi)存中讀取數(shù)據(jù)羹幸,提升速度和性能脊髓。

四辫愉、使用場景判斷

4.1 數(shù)據(jù)格式

  • 二進(jìn)制格式(不能確定是純文本):字節(jié)流,InputStream将硝、OutputStream及其子類恭朗。
  • 純文本格式(含中英文或其他編碼方式):字符流,Reader依疼,Writer及其子類痰腮。

4.2 數(shù)據(jù)來源

  • 文件:字節(jié)流 FileInputStream,F(xiàn)ileOutputStream律罢;字符流 FileReader膀值,F(xiàn)ileWriter
  • byte[]: 字節(jié)流 ByteArrayInputStream, ByteArrayOutputStream char[]:字符流
  • CharArrayReader, CharArrayWriter String: 字節(jié)
  • StringBufferInputStream, StringBufferOuputStream 棍丐;字符流 StringReader,StringWriter
  • 網(wǎng)絡(luò)數(shù)據(jù)流:字節(jié)流 InputStream, OutputStream;字符流 Reader, Writer

4.3 是否需要格式化輸出

需要格式化輸出的:PrintStream, PrintWriter

4.4 是否需要緩沖

需要緩沖:字節(jié)流 BufferedInputStream, BufferedOutputStream沧踏;字符流 BufferedReader, BufferedWriter

4.5 輸入還是輸出

  • 輸入:Reader, InputStream 類型的子類
  • 輸出:Writer, OutputStream 類型的子類

4.6 是否有流轉(zhuǎn)化

  • 字節(jié)到字符:InputStreamReader
  • 字符到字節(jié):OutputStreamWriter

4.7 特殊需要

  • 對象輸入輸出:ObjectInputStream, ObjectOutputStream
  • 進(jìn)程間通信:PipedInputStream, PipedOutputStream, PipedReader, PipedWriter
  • 合并輸入: SequenceInputStream
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末歌逢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子翘狱,更是在濱河造成了極大的恐慌秘案,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件潦匈,死亡現(xiàn)場離奇詭異阱高,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)茬缩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門赤惊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凰锡,你說我怎么就攤上這事荐捻。” “怎么了寡夹?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵处面,是天一觀的道長。 經(jīng)常有香客問我菩掏,道長魂角,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任智绸,我火速辦了婚禮野揪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瞧栗。我一直安慰自己斯稳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布迹恐。 她就那樣靜靜地躺著挣惰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪殴边。 梳的紋絲不亂的頭發(fā)上憎茂,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機(jī)與錄音锤岸,去河邊找鬼竖幔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛是偷,可吹牛的內(nèi)容都是我干的拳氢。 我是一名探鬼主播募逞,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼馋评!你這毒婦竟也來了凡辱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤栗恩,失蹤者是張志新(化名)和其女友劉穎透乾,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體磕秤,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乳乌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了市咆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汉操。...
    茶點(diǎn)故事閱讀 38,716評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蒙兰,靈堂內(nèi)的尸體忽然破棺而出磷瘤,到底是詐尸還是另有隱情,我是刑警寧澤搜变,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布采缚,位于F島的核電站,受9級特大地震影響挠他,放射性物質(zhì)發(fā)生泄漏扳抽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一殖侵、第九天 我趴在偏房一處隱蔽的房頂上張望贸呢。 院中可真熱鬧,春花似錦拢军、人聲如沸楞陷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽固蛾。三九已至,卻和暖如春赌渣,著一層夾襖步出監(jiān)牢的瞬間魏铅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工坚芜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人斜姥。 一個(gè)月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓鸿竖,卻偏偏與公主長得像沧竟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子缚忧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評論 2 350