JavaIO 總結(jié)筆記<六> 另類IO觀點(diǎn)概括

個(gè)人博客藏雏、個(gè)人簡書gitHub主頁

原文地址:http://www.cnblogs.com/xdp-gacl/p/3634409.html

一找爱、JAVA流式輸入/輸出原理

輸入/輸出原理

流是用來讀寫數(shù)據(jù)的梗顺,java有一個(gè)類叫File,它封裝的是文件的文件名车摄,只是內(nèi)存里面的一個(gè)對(duì)象寺谤,真正的文件是在硬盤上的一塊空間,在這個(gè)文件里面存放著各種各樣的數(shù)據(jù)吮播,我們想讀文件里面的數(shù)據(jù)怎么辦呢变屁?是通過一個(gè)流的方式來讀,咱們要想從程序讀數(shù)據(jù)意狠,對(duì)于計(jì)算機(jī)來說粟关,無論讀什么類型的數(shù)據(jù)都是以010101101010這樣的形式讀取的。怎么把文件里面的數(shù)據(jù)讀出來呢环戈?你可以把文件想象成一個(gè)小桶闷板,文件就是一個(gè)桶,文件里面的數(shù)據(jù)就相當(dāng)于是這個(gè)桶里面的水院塞,那么我們?cè)趺磸倪@個(gè)桶里面取水呢遮晚,也就是怎么從這個(gè)文件讀取數(shù)據(jù)呢。

常見的取水的辦法是我們用一根管道插到桶上面迫悠,然后在管道的另一邊打開水龍頭鹏漆,桶里面的水就開始嘩啦嘩啦地從水龍頭里流出來了,桶里面的水是通過這根管道流出來的创泄,因此這根管道就叫流艺玲,JAVA里面的流式輸入/輸出跟水流的原理一模一樣,當(dāng)你要從文件讀取數(shù)據(jù)的時(shí)候鞠抑,一根管道插到文件里面去饭聚,然后文件里面的數(shù)據(jù)就順著管道流出來,這時(shí)你在管道的另一頭就可以讀取到從文件流出來的各種各樣的數(shù)據(jù)了搁拙。當(dāng)你要往文件寫入數(shù)據(jù)時(shí)秒梳,也是通過一根管道法绵,讓要寫入的數(shù)據(jù)通過這根管道嘩啦嘩啦地流進(jìn)文件里面去。除了從文件去取數(shù)據(jù)以外酪碘,還可以通過網(wǎng)絡(luò)朋譬,比如用一根管道把我和你的機(jī)子連接起來,我說一句話兴垦,通過這個(gè)管道流進(jìn)你的機(jī)子里面徙赢,你馬上就可以看得到,而你說一句話探越,通過這根管道流到我的機(jī)子里面狡赐,我也馬上就可以看到。有的時(shí)候钦幔,一根管道不夠用枕屉,比方說這根管道流過來的水有一些雜質(zhì),我們就可以在這個(gè)根管道的外面再包一層管道鲤氢,把雜質(zhì)給過濾掉瘫筐。從程序的角度來講排抬,從計(jì)算機(jī)讀取到的原始數(shù)據(jù)肯定都是010101這種形式的皮迟,一個(gè)字節(jié)一個(gè)字節(jié)地往外讀庶喜,當(dāng)你這樣讀的時(shí)候你覺得這樣的方法不合適,沒關(guān)系揍庄,你再在這根管道的外面再包一層比較強(qiáng)大的管道咆蒿,這個(gè)管道可以把010101幫你轉(zhuǎn)換成字符串。這樣你使用程序讀取數(shù)據(jù)時(shí)讀到的就不再是010101這種形式的數(shù)據(jù)了蚂子,而是一些可以看得懂的字符串了沃测。

流是用來讀寫數(shù)據(jù)的,java有一個(gè)類叫File食茎,它封裝的是文件的文件名蒂破,只是內(nèi)存里面的一個(gè)對(duì)象,真正的文件是在硬盤上的一塊空間别渔,在這個(gè)文件里面存放著各種各樣的數(shù)據(jù)附迷,我們想讀文件里面的數(shù)據(jù)怎么辦呢?是通過一個(gè)流的方式來讀哎媚,咱們要想從程序讀數(shù)據(jù)喇伯,對(duì)于計(jì)算機(jī)來說,無論讀什么類型的數(shù)據(jù)都是以010101101010這樣的形式讀取的拨与。怎么把文件里面的數(shù)據(jù)讀出來呢稻据?你可以把文件想象成一個(gè)小桶,文件就是一個(gè)桶买喧,文件里面的數(shù)據(jù)就相當(dāng)于是這個(gè)桶里面的水捻悯,那么我們?cè)趺磸倪@個(gè)桶里面取水呢匆赃,也就是怎么從這個(gè)文件讀取數(shù)據(jù)呢。

常見的取水的辦法是我們用一根管道插到桶上面今缚,然后在管道的另一邊打開水龍頭算柳,桶里面的水就開始嘩啦嘩啦地從水龍頭里流出來了,桶里面的水是通過這根管道流出來的荚斯,因此這根管道就叫流埠居,JAVA里面的流式輸入/輸出跟水流的原理一模一樣,當(dāng)你要從文件讀取數(shù)據(jù)的時(shí)候事期,一根管道插到文件里面去,然后文件里面的數(shù)據(jù)就順著管道流出來纸颜,這時(shí)你在管道的另一頭就可以讀取到從文件流出來的各種各樣的數(shù)據(jù)了兽泣。當(dāng)你要往文件寫入數(shù)據(jù)時(shí),也是通過一根管道胁孙,讓要寫入的數(shù)據(jù)通過這根管道嘩啦嘩啦地流進(jìn)文件里面去唠倦。除了從文件去取數(shù)據(jù)以外,還可以通過網(wǎng)絡(luò)涮较,比如用一根管道把我和你的機(jī)子連接起來稠鼻,我說一句話,通過這個(gè)管道流進(jìn)你的機(jī)子里面狂票,你馬上就可以看得到候齿,而你說一句話,通過這根管道流到我的機(jī)子里面闺属,我也馬上就可以看到慌盯。有的時(shí)候,一根管道不夠用掂器,比方說這根管道流過來的水有一些雜質(zhì)亚皂,我們就可以在這個(gè)根管道的外面再包一層管道,把雜質(zhì)給過濾掉国瓮。從程序的角度來講灭必,從計(jì)算機(jī)讀取到的原始數(shù)據(jù)肯定都是010101這種形式的,一個(gè)字節(jié)一個(gè)字節(jié)地往外讀乃摹,當(dāng)你這樣讀的時(shí)候你覺得這樣的方法不合適禁漓,沒關(guān)系,你再在這根管道的外面再包一層比較強(qiáng)大的管道峡懈,這個(gè)管道可以把010101幫你轉(zhuǎn)換成字符串璃饱。這樣你使用程序讀取數(shù)據(jù)時(shí)讀到的就不再是010101這種形式的數(shù)據(jù)了,而是一些可以看得懂的字符串了肪康。

二荚恶、輸入輸出流分類

輸入輸出流分類

io包里面定義了所有的流撩穿,所以一說流指的就是io包里面的

什么叫輸入流?什么叫輸出流谒撼?用一根管道一端插進(jìn)文件里程序里面食寡,然后開始讀數(shù)據(jù),那么這是輸入還是輸出呢廓潜?如果站在文件的角度上抵皱,這叫輸出,如果站在程序的角度上辩蛋,這叫輸入呻畸。

記住,以后說輸入流和輸出流都是站在程序的角度上來說悼院。

三伤为、節(jié)點(diǎn)流和處理流

節(jié)點(diǎn)流和處理流

你要是對(duì)原始的流不滿意,你可以在這根管道外面再套其它的管道据途,套在其它管道之上的流叫處理流绞愚。為什么需要處理流呢?這就跟水流里面有雜質(zhì)颖医,你要過濾它位衩,你可以再套一層管道過濾這些雜質(zhì)一樣。

流里面有雜質(zhì)熔萧,你要過濾它糖驴,你可以再套一層管道過濾這些雜質(zhì)一樣哪痰。

3.1.節(jié)點(diǎn)流類型

節(jié)點(diǎn)流類型

節(jié)點(diǎn)流就是一根管道直接插到數(shù)據(jù)源上面,直接讀數(shù)據(jù)源里面的數(shù)據(jù)跷睦,或者是直接往數(shù)據(jù)源里面寫入數(shù)據(jù)。典型的節(jié)點(diǎn)流是文件流:文件的字節(jié)輸入流(FileInputStream)肋演,文件的字節(jié)輸出流(FileOutputStream)爹殊,文件的字符輸入流(FileReader)蜕乡,文件的字符輸出流(FileWriter)。

3.2.處理流類型

處理流類型

處理流是包在別的流上面的流梗夸,相當(dāng)于是包到別的管道上面的管道。

四辛块、InputStream(輸入流)

InputStream

我們看到的具體的某一些管道润绵,凡是以InputStream結(jié)尾的管道,都是以字節(jié)的形式向我們的程序輸入數(shù)據(jù)憨愉。

4.1.InputStream的基本方法

InputStream的基本方法
  read()方法是一個(gè)字節(jié)一個(gè)字節(jié)地往外讀配紫,每讀取一個(gè)字節(jié)娇澎,就處理一個(gè)字節(jié)趟庄。read(byte[] buffer)方法讀取數(shù)據(jù)時(shí)伪很,先把讀取到的數(shù)據(jù)填滿這個(gè)byte[]類型的數(shù)組buffer(buffer是內(nèi)存里面的一塊緩沖區(qū))锉试,然后再處理數(shù)組里面的數(shù)據(jù)。這就跟我們?nèi)∷粯油显疲扔靡粋€(gè)桶去接应又,等桶接滿水后再處理桶里面的水株扛。如果是每讀取一個(gè)字節(jié)就處理一個(gè)字節(jié),這樣子讀取也太累了洞就。

五旬蟋、OutputStream(輸出流)

OutputStream(輸出流)

5.1.OutputStream的基本方法

OutputStream的基本方法

六、Reader流

Reader流

6.1.Reader的基本方法

Reader的基本方法

七拦惋、Writer流

Writer流

7.1.Writer的基本方法

Writer的基本方法

八鸣哀、節(jié)點(diǎn)流講解

以File(文件)這個(gè)類型作為講解節(jié)點(diǎn)流的典型代表

節(jié)點(diǎn)流講解
  • 范例:使用FileInputStream流來讀取FileInputStream.java文件的內(nèi)容

public class TestFileInputStream {
    public static void main(String args[]) {
        int b = 0;// 使用變量b來裝調(diào)用read()方法時(shí)返回的整數(shù)
        FileInputStream in = null;
        // 使用FileInputStream流來讀取有中文的內(nèi)容時(shí)我衬,讀出來的是亂碼挠羔,因?yàn)槭褂肐nputStream流里面的read()方法讀取內(nèi)容時(shí)是一個(gè)字節(jié)一個(gè)字節(jié)地讀取的井仰,而一個(gè)漢字是占用兩個(gè)字節(jié)的俱恶,所以讀取出來的漢字無法正確顯示范舀。
        // FileReader in = null;//使用FileReader流來讀取內(nèi)容時(shí)锭环,中英文都可以正確顯示聪全,因?yàn)镽eader流里面的read()方法是一個(gè)字符一個(gè)字符地讀取的辅辩,這樣每次讀取出來的都是一個(gè)完整的漢字玫锋,這樣就可以正確顯示了。
        try {
            in = new FileInputStream("D:\\Java\\MyEclipse 10\\Workspaces\\AnnotationTest\\src\\cn\\galc\\test\\FileInputStream.java");
            // in = new FileReader("D:/java/io/TestFileInputStream.java");
        } catch (FileNotFoundException e) {
            System.out.println("系統(tǒng)找不到指定文件谦炬!");
            System.exit(-1);// 系統(tǒng)非正常退出
        }
        long num = 0;// 使用變量num來記錄讀取到的字符數(shù)
        try {// 調(diào)用read()方法時(shí)會(huì)拋異常三痰,所以需要捕獲異常
            while ((b = in.read()) != -1) {
                // 調(diào)用int read() throws Exception方法時(shí)散劫,返回的是一個(gè)int類型的整數(shù)
                // 循環(huán)結(jié)束的條件就是返回一個(gè)值-1,表示此時(shí)已經(jīng)讀取到文件的末尾了赖条。
                // System.out.print(b+"\t");//如果沒有使用“(char)b”進(jìn)行轉(zhuǎn)換纬乍,那么直接打印出來的b就是數(shù)字,而不是英文和中文了
                System.out.print((char) b);
                // “char(b)”把使用數(shù)字表示的漢字和英文字母轉(zhuǎn)換成字符輸入
                num++;
            }
            in.close();// 關(guān)閉輸入流
            System.out.println();
            System.out.println("總共讀取了" + num + "個(gè)字節(jié)的文件");
        } catch (IOException e1) {
            System.out.println("文件讀取錯(cuò)誤纽竣!");
        }
    }
}

  • 范例:使用FileOutputStream流往一個(gè)文件里面寫入數(shù)據(jù)

public class TestFileOutputStream {
    public static void main(String args[]) {
        int b = 0;
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            in = new FileInputStream("D:\\Java\\MyEclipse 10\\Workspaces\\AnnotationTest\\src\\cn\\galc\\test\\MyMouseAdapter.java");
            out = new FileOutputStream("D:/java/TestFileOutputStream1.java");
            // 指明要寫入數(shù)據(jù)的文件蜓氨,如果指定的路徑中不存在TestFileOutputStream1.java這樣的文件穴吹,則系統(tǒng)會(huì)自動(dòng)創(chuàng)建一個(gè)
            while ((b = in.read()) != -1) {
                out.write(b);
                // 調(diào)用write(int c)方法把讀取到的字符全部寫入到指定文件中去
            }
            in.close();
            out.close();
        } catch (FileNotFoundException e) {
            System.out.println("文件讀取失敗");
            System.exit(-1);// 非正常退出
        } catch (IOException e1) {
            System.out.println("文件復(fù)制失敻哿睢锈颗!");
            System.exit(-1);
        }
        System.out
                .println("TestFileInputStream.java文件里面的內(nèi)容已經(jīng)成功復(fù)制到文件TestFileOutStream1.java里面");
    }
}

FileInputStream和FileOutputStream這兩個(gè)流都是字節(jié)流击吱,都是以一個(gè)字節(jié)為單位進(jìn)行輸入和輸出的姨拥。所以對(duì)于占用2個(gè)字節(jié)存儲(chǔ)空間的字符來說讀取出來時(shí)就會(huì)顯示成亂碼叫乌。

  • 范例:使用FileWriter(字符流)向指定文件中寫入數(shù)據(jù)

/*使用FileWriter(字符流)向指定文件中寫入數(shù)據(jù)
寫入數(shù)據(jù)時(shí)以1個(gè)字符為單位進(jìn)行寫入*/
public class TestFileWriter{
    public static void main(String args[]){
        /*使用FileWriter輸出流從程序把數(shù)據(jù)寫入到Uicode.dat文件中
        使用FileWriter流向文件寫入數(shù)據(jù)時(shí)是一個(gè)字符一個(gè)字符寫入的*/
        FileWriter fw = null;
        try{
                fw = new FileWriter("D:/java/Uicode.dat");
                //字符的本質(zhì)是一個(gè)無符號(hào)的16位整數(shù)
                //字符在計(jì)算機(jī)內(nèi)部占用2個(gè)字節(jié)
                //這里使用for循環(huán)把0~60000里面的所有整數(shù)都輸出
                //這里相當(dāng)于是把全世界各個(gè)國家的文字都0~60000內(nèi)的整數(shù)的形式來表示
                for(int c=0;c<=60000;c++){
                    fw.write(c);
                    //使用write(int c)把0~60000內(nèi)的整數(shù)寫入到指定文件內(nèi)
                    //調(diào)用write()方法時(shí)憨奸,我認(rèn)為在執(zhí)行的過程中應(yīng)該使用了“(char)c”進(jìn)行強(qiáng)制轉(zhuǎn)換凿试,即把整數(shù)轉(zhuǎn)換成字符來顯示
                    //因?yàn)榇蜷_寫入數(shù)據(jù)的文件可以看到那婉,里面顯示的數(shù)據(jù)并不是0~60000內(nèi)的整數(shù)详炬,而是不同國家的文字的表示方式
            }
            /*使用FileReader(字符流)讀取指定文件里面的內(nèi)容
            讀取內(nèi)容時(shí)是以一個(gè)字符為單位進(jìn)行讀取的*/
                int b = 0;
                long num = 0;
                FileReader fr = null;
                fr = new FileReader("D:/java/Uicode.dat");
                while((b = fr.read())!= -1){
                    System.out.print((char)b + "\t");
                    num++;
                }
                System.out.println();
                System.out.println("總共讀取了"+num+"個(gè)字符");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

FileReader和FileWriter這兩個(gè)流都是字符流,都是以一個(gè)字符為單位進(jìn)行輸入和輸出的在跳。所以讀取和寫入占用2個(gè)字節(jié)的字符時(shí)都可以正常地顯示出來猫妙,以上是以File(文件)這個(gè)類型為例對(duì)節(jié)點(diǎn)流進(jìn)行了講解割坠,所謂的節(jié)點(diǎn)流指定就是直接把輸入流或輸出插入到數(shù)據(jù)源上,直接往數(shù)據(jù)源里面寫入數(shù)據(jù)或讀取數(shù)據(jù)童谒。

九饥伊、處理流講解

9.1.第一種處理流——緩沖流(Buffering)

節(jié)點(diǎn)流講解

帶有緩沖區(qū)的琅豆,緩沖區(qū)(Buffer)就是內(nèi)存里面的一小塊區(qū)域篓吁,讀寫數(shù)據(jù)時(shí)都是先把數(shù)據(jù)放到這塊緩沖區(qū)域里面杖剪,減少io對(duì)硬盤的訪問次數(shù)盛嘿,保護(hù)我們的硬盤「遘裕可以把緩沖區(qū)想象成一個(gè)小桶漓库,把要讀寫的數(shù)據(jù)想象成水园蝠,每次讀取數(shù)據(jù)或者是寫入數(shù)據(jù)之前砰琢,都是先把數(shù)據(jù)裝到這個(gè)桶里面,裝滿了以后再做處理训唱。這就是所謂的緩沖况增。先把數(shù)據(jù)放置到緩沖區(qū)上澳骤,等到緩沖區(qū)滿了以后,再一次把緩沖區(qū)里面的數(shù)據(jù)寫入到硬盤上或者讀取出來摊册,這樣可以有效地減少對(duì)硬盤的訪問次數(shù)茅特,有利于保護(hù)我們的硬盤棋枕。

  • 緩沖流測試代碼:

public class TestBufferStream {
    public static void main(String args[]) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("D:/java/TestFileInputStream.java");
            // 在FileInputStream節(jié)點(diǎn)流的外面套接一層處理流BufferedInputStream
            BufferedInputStream bis = new BufferedInputStream(fis);
            int c = 0;
            System.out.println((char) bis.read());
            System.out.println((char) bis.read());
            bis.mark(100);// 在第100個(gè)字符處做一個(gè)標(biāo)記
            for (int i = 0; i <= 10 && (c = bis.read()) != -1; i++) {
                System.out.print((char) c);
            }
            System.out.println();
            bis.reset();// 重新回到原來標(biāo)記的地方
            for (int i = 0; i <= 10 && (c = bis.read()) != -1; i++) {
                System.out.print((char) c);
            }
            bis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }
}


  public class TestBufferStream1{
      public static void main(String args[]){
          try{
          BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\java\\dat.txt"));
              //在節(jié)點(diǎn)流FileWriter的外面再套一層處理流BufferedWriter
              String s = null;
              for(int i=0;i<100;i++){
                  s = String.valueOf(Math.random());//“Math.random()”將會(huì)生成一系列介于0~1之間的隨機(jī)數(shù)兵睛。
                  // static String valueOf(double d)這個(gè)valueOf()方法的作用就是把一個(gè)double類型的數(shù)轉(zhuǎn)換成字符串
                  //valueOf()是一個(gè)靜態(tài)方法祖很,所以可以使用“類型.靜態(tài)方法名”的形式來調(diào)用 
                  bw.write(s);//把隨機(jī)數(shù)字符串寫入到指定文件中
                  bw.newLine();//調(diào)用newLine()方法使得每寫入一個(gè)隨機(jī)數(shù)就換行顯示
              }
              bw.flush();//調(diào)用flush()方法清空緩沖區(qū)
              
          BufferedReader br = new BufferedReader(new FileReader("D:/java/dat.txt"));
                  //在節(jié)點(diǎn)流FileReader的外面再套一層處理流BufferedReader
              while((s = br.readLine())!=null){
                  //使用BufferedReader處理流里面提供String readLine()方法讀取文件中的數(shù)據(jù)時(shí)是一行一行讀取的
                  //循環(huán)結(jié)束的條件就是使用readLine()方法讀取數(shù)據(jù)返回的字符串為空值后則表示已經(jīng)讀取到文件的末尾了突琳。
                  System.out.println(s);
                  
              }
          bw.close();
          br.close();
          }catch(Exception e){
              e.printStackTrace();
          }
      }
  } 

節(jié)點(diǎn)流講解

程序的輸入指的是把從文件讀取到的內(nèi)容存儲(chǔ)到為程序分配的內(nèi)存區(qū)域里面去。流啊终,什么是流傲须,流無非就是兩根管道泰讽,一根向里,一根向外佛玄,向里向外都是對(duì)于我們自己寫的程序來說梦抢,流分為各種各樣的類型奥吩,不同的分類方式又可以分為不同的類型,根據(jù)方向來分腮介,分為輸入流和輸出流叠洗,根據(jù)讀取數(shù)據(jù)的單位的不同靴迫,又可以分為字符流和字節(jié)流玉锌,除此之外主守,還可以分為節(jié)點(diǎn)流和處理流,節(jié)點(diǎn)流就是直接和數(shù)據(jù)源連接的流救湖,處理流就是包在其它流上面的流鞋既,處理流不是直接和數(shù)據(jù)源連接邑闺,而是從數(shù)據(jù)源讀取到數(shù)據(jù)以后再通過處理流處理一遍棕兼。緩沖流也包含了四個(gè)類:BufferedInputStream伴挚、BufferedOutputStream、BufferedReader和BufferedWriter蜈出。流都是成對(duì)的帚呼,沒有流是是不成對(duì)的煤杀,肯定是一個(gè)in沈自,一個(gè)out。

9.2.第二種處理流——轉(zhuǎn)換流

節(jié)點(diǎn)流講解

轉(zhuǎn)換流非常的有用忌怎,它可以把一個(gè)字節(jié)流轉(zhuǎn)換成一個(gè)字符流酪夷,轉(zhuǎn)換流有兩種晚岭,一種叫InputStreamReader坦报,另一種叫OutputStreamWriter。InputStream是字節(jié)流潜的,Reader是字符流啰挪,InputStreamReader就是把InputStream轉(zhuǎn)換成Reader脐供。OutputStream是字節(jié)流借跪,Writer是字符流掏愁,OutputStreamWriter就是把OutputStream轉(zhuǎn)換成Writer果港。把OutputStream轉(zhuǎn)換成Writer之后就可以一個(gè)字符一個(gè)字符地通過管道寫入數(shù)據(jù)了,而且還可以寫入字符串谢谦。我們?nèi)绻靡粋€(gè)FileOutputStream流往文件里面寫東西回挽,得要一個(gè)字節(jié)一個(gè)字節(jié)地寫進(jìn)去千劈,但是如果我們?cè)贔ileOutputStream流上面套上一個(gè)字符轉(zhuǎn)換流牌捷,那我們就可以一個(gè)字符串一個(gè)字符串地寫進(jìn)去暗甥。

轉(zhuǎn)換流測試代碼:


public class TestTransform1 {
    public static void main(String args[]) {
        try {
            OutputStreamWriter osw = new OutputStreamWriter(
                    new FileOutputStream("D:/java/char.txt"));
            osw.write("MircosoftsunIBMOracleApplet");// 把字符串寫入到指定的文件中去
            System.out.println(osw.getEncoding());// 使用getEncoding()方法取得當(dāng)前系統(tǒng)的默認(rèn)字符編碼
            osw.close();
            osw = new OutputStreamWriter(new FileOutputStream(
                    "D:\\java\\char.txt", true), "ISO8859_1");
            // 如果在調(diào)用FileOutputStream的構(gòu)造方法時(shí)沒有加入true撤防,那么新加入的字符串就會(huì)替換掉原來寫入的字符串即碗,在調(diào)用構(gòu)造方法時(shí)指定了字符的編碼
            osw.write("MircosoftsunIBMOracleApplet");// 再次向指定的文件寫入字符串剥懒,新寫入的字符串加入到原來字符串的后面
            System.out.println(osw.getEncoding());
            osw.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

節(jié)點(diǎn)流講解

import java.io.*;
public class TestTransform2{
    public static void main(String args[]){
        try{
            InputStreamReader isr = new InputStreamReader(System.in);
            //System.in這里的in是一個(gè)標(biāo)準(zhǔn)的輸入流初橘,用來接收從鍵盤輸入的數(shù)據(jù)
            BufferedReader br = new BufferedReader(isr);
            String s = null;
            s = br.readLine();//使用readLine()方法把讀取到的一行字符串保存到字符串變量s中去
            while(s != null){
                System.out.println(s.toUpperCase());//把保存在內(nèi)存s中的字符串打印出來
                s = br.readLine();//在循環(huán)體內(nèi)繼續(xù)接收從鍵盤的輸入
                if(s.equalsIgnoreCase("exit")){
                    //只要輸入exit循環(huán)就結(jié)束保檐,就會(huì)退出
                    break;
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

9.3.第三種處理流——數(shù)據(jù)流

節(jié)點(diǎn)流講解

數(shù)據(jù)流測試代碼:

public class TestDataStream{
    public static void main(String args[]){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        //在調(diào)用構(gòu)造方法時(shí)垒在,首先會(huì)在內(nèi)存里面創(chuàng)建一個(gè)ByteArray字節(jié)數(shù)組
        DataOutputStream dos = new DataOutputStream(baos);
        //在輸出流的外面套上一層數(shù)據(jù)流场躯,用來處理int,double類型的數(shù)
        try{
            dos.writeDouble(Math.random());//把產(chǎn)生的隨機(jī)數(shù)直接寫入到字節(jié)數(shù)組ByteArray中
            dos.writeBoolean(true);//布爾類型的數(shù)據(jù)在內(nèi)存中就只占一個(gè)字節(jié)
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            System.out.println(bais.available());
            DataInputStream dis = new DataInputStream(bais);
            System.out.println(dis.readDouble());//先寫進(jìn)去的就先讀出來伞鲫,調(diào)用readDouble()方法讀取出寫入的隨機(jī)數(shù)
            System.out.println(dis.readBoolean());//后寫進(jìn)去的就后讀出來秕脓,這里面的讀取順序不能更改位置吠架,否則會(huì)打印出不正確的結(jié)果
            dos.close();
            bais.close();
        }catch(Exception e){
                e.printStackTrace();
            }
    }
}

通過bais這個(gè)流往外讀取數(shù)據(jù)的時(shí)候诵肛,是一個(gè)字節(jié)一個(gè)字節(jié)地往外讀取的怔檩,因此讀出來的數(shù)據(jù)無法判斷是字符串還是bool類型的值蓄诽,因此要在它的外面再套一個(gè)流仑氛,通過dataInputStream把讀出來的數(shù)據(jù)轉(zhuǎn)換就可以判斷了锯岖。注意了:讀取數(shù)據(jù)的時(shí)候是先寫進(jìn)去的就先讀出來,因此讀ByteArray字節(jié)數(shù)組數(shù)據(jù)的順序應(yīng)該是先把占8個(gè)字節(jié)的double類型的數(shù)讀出來遇伞,然后再讀那個(gè)只占一個(gè)字節(jié)的boolean類型的數(shù)鸠珠,因?yàn)閐ouble類型的數(shù)是先寫進(jìn)數(shù)組里面的渐排,讀的時(shí)候也要先讀它驯耻。這就是所謂的先寫的要先讀。如果先讀Boolean類型的那個(gè)數(shù)孽水,那么讀出來的情況可能就是把double類型數(shù)的8個(gè)字節(jié)里面的一個(gè)字節(jié)讀了出來。

9.4.打印流——Print

節(jié)點(diǎn)流講解

測試代碼:


/*這個(gè)小程序是重新設(shè)置打印輸出的窗口杏慰,
 * 把默認(rèn)在命令行窗口輸出打印內(nèi)容設(shè)置成其他指定的打印顯示窗口
 */
import java.io.*;
public class TestPrintStream{
    public static void main(String args[]){
        PrintStream ps = null;
        try{
                FileOutputStream fos = new FileOutputStream("D:/java/log.txt");
                ps = new PrintStream(fos);//在輸出流的外面套接一層打印流测柠,用來控制打印輸出
                if(ps != null){
                    System.setOut(ps);//這里調(diào)用setOut()方法改變了輸出窗口,以前寫System.out.print()默認(rèn)的輸出窗口就是命令行窗口.
                    //但現(xiàn)在使用System.setOut(ps)將打印輸出窗口改成了由ps指定的文件里面缘滥,通過這樣設(shè)置以后轰胁,打印輸出時(shí)都會(huì)在指定的文件內(nèi)打印輸出
                    //在這里將打印輸出窗口設(shè)置到了log.txt這個(gè)文件里面,所以打印出來的內(nèi)容會(huì)在log.txt這個(gè)文件里面看到
                }
            for(char c=0;c<=60000;c++){
                    System.out.print(c+"\t");//把世界各國的文字打印到log.txt這個(gè)文件中去
                }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

節(jié)點(diǎn)流講解

9.5. 對(duì)象流——Object

節(jié)點(diǎn)流講解

測試代碼:


public class TestObjectIo {
    public static void main(String args[]) {
        T t = new T();
        t.k = 8;// 把k的值修改為8
        try {
            FileOutputStream fos = new FileOutputStream(
                    "D:/java/TestObjectIo.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            // ObjectOutputStream流專門用來處理Object的朝扼,在fos流的外面套接ObjectOutputStream流就可以直接把一個(gè)Object寫進(jìn)去
            oos.writeObject(t);// 直接把一個(gè)t對(duì)象寫入到指定的文件里面
            oos.flush();
            oos.close();
            FileInputStream fis = new FileInputStream(
                    "D:/java/TestObjectIo.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            // ObjectInputStream專門用來讀一個(gè)Object的
            T tRead = (T) ois.readObject();
            // 直接把文件里面的內(nèi)容全部讀取出來然后分解成一個(gè)Object對(duì)象,并使用強(qiáng)制轉(zhuǎn)換成指定類型T
            System.out.print(tRead.i + "\t" + tRead.j + "\t" + tRead.d + "\t"
                    + tRead.k);
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/*
 * 凡是要將一個(gè)類的對(duì)象序列化成一個(gè)字節(jié)流就必須實(shí)現(xiàn)Serializable接口
 * Serializable接口中沒有定義方法擎颖,Serializable接口是一個(gè)標(biāo)記性接口榛斯,用來給類作標(biāo)記,只是起到一個(gè)標(biāo)記作用搂捧。
 * 這個(gè)標(biāo)記是給編譯器看的驮俗,編譯器看到這個(gè)標(biāo)記之后就可以知道這個(gè)類可以被序列化 如果想把某個(gè)類的對(duì)象序列化,就必須得實(shí)現(xiàn)Serializable接口
 */
class T implements Serializable {
    // Serializable的意思是可以被序列化的
    int i = 10;
    int j = 9;
    double d = 2.3;
    int k = 15;
    // transient int k = 15;
    // 在聲明變量時(shí)如果加上transient關(guān)鍵字允跑,那么這個(gè)變量就會(huì)被當(dāng)作是透明的王凑,即不存在。
}

直接實(shí)現(xiàn)Serializable接口的類是JDK自動(dòng)把這個(gè)類的對(duì)象序列化聋丝,而如果實(shí)現(xiàn)public interface Externalizable extends Serializable的類則可以自己控制對(duì)象的序列化索烹,建議能讓JDK自己控制序列化的就不要讓自己去控制。

十弱睦、IO流總結(jié)

節(jié)點(diǎn)流講解

項(xiàng)目地址:傳送門

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末百姓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子每篷,更是在濱河造成了極大的恐慌瓣戚,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焦读,死亡現(xiàn)場離奇詭異子库,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)矗晃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門仑嗅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事仓技⊥冶幔” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵脖捻,是天一觀的道長阔逼。 經(jīng)常有香客問我,道長地沮,這世上最難降的妖魔是什么嗜浮? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮摩疑,結(jié)果婚禮上危融,老公的妹妹穿的比我還像新娘。我一直安慰自己雷袋,他們只是感情好吉殃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著楷怒,像睡著了一般蛋勺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上率寡,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天迫卢,我揣著相機(jī)與錄音,去河邊找鬼冶共。 笑死乾蛤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捅僵。 我是一名探鬼主播家卖,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼庙楚!你這毒婦竟也來了上荡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤馒闷,失蹤者是張志新(化名)和其女友劉穎酪捡,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纳账,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逛薇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疏虫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片永罚。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡啤呼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呢袱,到底是詐尸還是另有隱情官扣,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布羞福,位于F島的核電站惕蹄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏治专。R本人自食惡果不足惜焊唬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望看靠。 院中可真熱鬧,春花似錦液肌、人聲如沸挟炬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谤祖。三九已至,卻和暖如春老速,著一層夾襖步出監(jiān)牢的瞬間粥喜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國打工橘券, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留额湘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓旁舰,卻偏偏與公主長得像锋华,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子箭窜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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