Java 字符流操作

?????上篇文章Java 字節(jié)流操作介紹了java中基本的字節(jié)流操作俐镐,但是我們常常對于字符操作,如果使用字節(jié)流來實現(xiàn)輸入輸出就顯得麻煩碘梢,我們可以使用字符流來實現(xiàn)對我們看得見的字符char進行操作蜈块,主要內(nèi)容如下:

  • 基本流(Reader/Writer)
  • 轉(zhuǎn)換流(InputStreamReader/OutputStreamEWriter)
  • 文件字符流(FileReader/FileWriter)
  • 字符數(shù)組流(charArrayReader/charArrayWriter)
  • 緩沖字符流(BufferedReader/BufferedWriter)
  • 裝飾類(PrintWriter)
    一、基本流
    ?????字節(jié)流的基本流是InputStream/OutputStream这嚣,這里的字符流的基本流是Reader/Writer,他們都是抽象類塞俱,想要實現(xiàn)更加復(fù)雜的操作就必須要子類來擴充姐帚。他們內(nèi)部主要的就是read和write方法,實現(xiàn)單個字符及字符數(shù)組的讀取的寫入障涯。此處就不再列出罐旗,我們將會從他們的子類中看看這些方法的實現(xiàn)。
    二唯蝶、轉(zhuǎn)換流
    ?????InputStreamReader和OutputStreamWriter這兩個類型流九秀,在整個字符流中是十分重要的流,他們實現(xiàn)了和字節(jié)流的轉(zhuǎn)換粘我。先看看InputStreamReader:
private final StreamDecoder sd;

public InputStreamReader(InputStream in)
public InputStreamReader(InputStream in, String charsetName)
public InputStreamReader(InputStream in, Charset cs)
public InputStreamReader(InputStream in, CharsetDecoder dec)

public int read() throws IOException {
        return sd.read();
    }
public int read(char cbuf[], int offset, int length) throws IOException {
        return sd.read(cbuf, offset, length);
    }

?????首先定義了一個StreamDecoder 類型的常量(這是一個十分重要的成員)鼓蜒,一堆構(gòu)造方法通過不同的方式指定了外部傳入的InputStream類型的參數(shù)和解碼類型。我們看到,read方法中調(diào)用的是上述的sd常量(這是一個StreamDecoder類型的常量)的方法都弹。這個StreamDecoder類實際上完成了將字節(jié)轉(zhuǎn)換成char的操作娇豫。

public class Test_InputOrOutput {
    public static void main(String[] args) throws IOException{

        InputStreamReader inr = new InputStreamReader(new FileInputStream("hello.txt"));
        char[] chs = new char[100];
        inr.read(chs);
        System.out.println(chs);
        inr.close();
    }
}

?????上述代碼展示了如何從文件中按照指定的解碼方式讀取出字符,OutputStreamWriter幾乎是逆操作:

public void write(int c)
public void write(char cbuf[], int off, int len)
public void write(String str, int off, int len)

?????可以寫int畅厢,可以寫char數(shù)組锤躁,還可以寫字符串(實際上還是調(diào)用了getchars方法獲取該字符串的內(nèi)置char數(shù)組,然后調(diào)用寫數(shù)組的方法)或详。

public class Test_InputOrOutput {
    public static void main(String[] args) throws IOException{

       OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("hello.txt"));
        ow.write("walker");
        ow.close();
    }
}
/*可以明顯感知,對字符操作的簡單直接*/

三郭计、文件字符流
????? FileReader和FileWriter兩個流霸琴,繼承的是上述的兩個轉(zhuǎn)換流。內(nèi)部的方法非常簡單昭伸,只是幾個構(gòu)造方法而已梧乘。

public FileReader(String fileName) throws FileNotFoundException {
        super(new FileInputStream(fileName));
    }
public FileReader(File file) throws FileNotFoundException {
        super(new FileInputStream(file));
    }


public FileWriter(String fileName) throws IOException {
        super(new FileOutputStream(fileName));
    }
public FileWriter(String fileName, boolean append) throws IOException {
        super(new FileOutputStream(fileName, append));
    }
public FileWriter(File file) throws IOException {
        super(new FileOutputStream(file));
    }

?????從源代碼中可以看出來,這兩個文件流完全依賴父類庐杨。自己基本沒有擴展父類选调,使用的方法都是父類的。你可以通過傳文件的路徑或者構(gòu)建File類作為構(gòu)造參數(shù)傳入灵份。

public class Test_InputOrOutput {
    public static void main(String[] args) throws IOException{

        FileReader fr = new FileReader("hello.txt");
        char[] chars = new char[1024];
        fr.read(chars);
        System.out.println(chars);
    }
}

?????一樣可以達到讀取字符的效果仁堪,實際上上述代碼可以轉(zhuǎn)換為:

public class Test_InputOrOutput {
    public static void main(String[] args) throws IOException{

        InputStreamReader ins = new InputStreamReader(new FileInputStream("hello.txt"));
        char[] chars = new char[1024];
        ins.read(chars);
        System.out.println(chars);
    }
}
//因為FIleReader的內(nèi)部還是通過super調(diào)用父類的構(gòu)造方法

四、字符數(shù)組流
?????和之前介紹的字節(jié)數(shù)組流類似填渠,都是為了能提高效率防止內(nèi)存浪費而設(shè)計的弦聂。看看我們上面的一段代碼:

public class Test_InputOrOutput {
    public static void main(String[] args) throws IOException{

        FileReader fr = new FileReader("hello.txt");
        char[] chars = new char[1024];
        fr.read(chars);
        System.out.println(chars);
    }
}

?????這段程序其實是不完善的氛什,因為我們默認hello文件中的字符容量小于等于1024莺葫,那如果文件足夠大,我們勢必要創(chuàng)建更大的字符數(shù)組(這是一種浪費內(nèi)存)枪眉。我們可以使用字符數(shù)組流來實現(xiàn)動態(tài)擴容捺檬,解決內(nèi)存空間。上述代碼可以改寫:

public class Test_InputOrOutput {
    public static void main(String[] args) throws IOException{

        FileReader fr = new FileReader("hello.txt");
        int x = 0;
        CharArrayWriter chw = new CharArrayWriter();
        while ((x = fr.read()) != -1){
            chw.write(x);
        }
        System.out.println(chw.toString());
        chw.close();
    }
}

?????這樣贸铜,即使文件再大堡纬,我們也不會浪費很多內(nèi)存空間。至于StingReader和StringWriter兩個流其實是類似的萨脑,因為String的本質(zhì)是char數(shù)組隐轩, 所以他們必然也是有數(shù)組作為最基本的操作。
五渤早、緩沖字符流
?????字符的緩沖流和字節(jié)的緩沖流是類似的职车。都是裝飾流。

public class Test_InputOrOutput {
    public static void main(String[] args) throws IOException{

        BufferedReader bins = new BufferedReader(new FileReader("hello.txt"));
        BufferedWriter bws = new BufferedWriter(new FileWriter("hello.txt",true));
        int x;
        while ((x = bins.read()) != -1){
            System.out.println((char)x);
            bws.write(x);
        }
    }
}
//緩沖讀和緩沖寫

六、PrintWriter
?????這是一個繼承與Writer的流悴灵,他是一個非常方便的類扛芽,可以直接指定文件名作為參數(shù),可以指定編碼類型积瞒,還支持自動緩沖技術(shù)川尖,可以自動轉(zhuǎn)換多種基本類型為字符串形式寫入文件中。在我們?nèi)粘J褂脤懭胛募r茫孔,可以優(yōu)先考慮使用該類叮喳。

protected Writer out;
private final boolean autoFlush;
//構(gòu)造方法
public PrintWriter (Writer out) {
        this(out, false);
    }
public PrintWriter(OutputStream out) {
        this(out, false);
    }
public PrintWriter(String fileName) throws FileNotFoundException {
        this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
             false);
public PrintWriter(File file) throws FileNotFoundException {
        this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
             false);
    }
//寫入一個character    
public void write(int c) {
        try {
            synchronized (lock) {
                ensureOpen();
                out.write(c);
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
//寫入一個字符串    
public void write(String s) {
        write(s, 0, s.length());
    }

//重載print方法
public void print(boolean b) {
        write(b ? "true" : "false");
    }
public void print(char c) {
        write(c);
    }
 
public void print(int i) {
        write(String.valueOf(i));
    }
    
public void println() {
        newLine();
    }
public void println(int x) {
        synchronized (lock) {
            print(x);
            println();
        }
    }
public void println(String x) {
        synchronized (lock) {
            print(x);
            println();
        }
    }   

?????上述代碼中的print和println并非和我們的標準輸出流(System.out.println)同義,這里的print表示寫入到文件中缰贝。

public class Test_InputOrOutput {
    public static void main(String[] args) throws IOException{

        PrintWriter pw = new PrintWriter("hello.txt");
        pw.println('x');
        pw.close();
     }
}

?????使用了PrintWriter寫入到文件中馍悟,非常的簡單方便,可以指定文件路徑剩晴,F(xiàn)ile锣咒,OutputStream作為構(gòu)造方法的形參。這一切的轉(zhuǎn)換都封裝了赞弥,自動提供緩沖流毅整。這是一種比較好的輸出流,在之后的使用中绽左,如果遇到輸出到文件悼嫉,應(yīng)該優(yōu)先考慮PrintWriter。
?????本篇文章結(jié)束了拼窥,這兩篇文章是我閱讀書籍和博客承粤,加上jdk源代碼總結(jié)得來,如有錯誤闯团,望大家指出辛臊!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市房交,隨后出現(xiàn)的幾起案子彻舰,更是在濱河造成了極大的恐慌,老刑警劉巖候味,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刃唤,死亡現(xiàn)場離奇詭異,居然都是意外死亡白群,警方通過查閱死者的電腦和手機尚胞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帜慢,“玉大人笼裳,你說我怎么就攤上這事唯卖。” “怎么了躬柬?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵拜轨,是天一觀的道長。 經(jīng)常有香客問我允青,道長橄碾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任颠锉,我火速辦了婚禮法牲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘琼掠。我一直安慰自己皆串,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布眉枕。 她就那樣靜靜地躺著,像睡著了一般怜森。 火紅的嫁衣襯著肌膚如雪速挑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天副硅,我揣著相機與錄音姥宝,去河邊找鬼。 笑死恐疲,一個胖子當(dāng)著我的面吹牛腊满,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播培己,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼碳蛋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了省咨?” 一聲冷哼從身側(cè)響起肃弟,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎零蓉,沒想到半個月后笤受,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡敌蜂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年箩兽,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片章喉。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡汗贫,死狀恐怖身坐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芳绩,我是刑警寧澤掀亥,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站妥色,受9級特大地震影響搪花,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嘹害,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一撮竿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笔呀,春花似錦幢踏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至微渠,卻和暖如春搭幻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逞盆。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工檀蹋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人云芦。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓俯逾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舅逸。 傳聞我的和親對象是個殘疾皇子桌肴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容