IO流 之 節點流與處理流


1. 流的分類
按數據流的方向不同輸入流,輸出流
按處理數據單位不同字節流,字符流
(1) 字節流:數據流中最小的數據單元是字節
(2)字符流:數據流中最小的數據單元是字符Java中的字符是Unicode編碼,一個字符占用兩個字節。
功能不同節點流,處理流
(1)程序用於直接操作目標設備所對應的類叫節點流。
(2)程序通過一個間接流類去調用節點流類,以達到更加靈活方便地讀寫各種類型的數據,這個間接流類就是處理流。
2. 節點流
2.1 節點流的類型

 


(1)File 文件流。對文件進行讀、寫操作 :FileReader、FileWriter、FileInputStream、FileOutputStream。、
(2)Memory
1)從/向內存數組讀寫數據: CharArrayReader與 CharArrayWriter、ByteArrayInputStream與ByteArrayOutputStream。
2)從/向內存字符串讀寫數據 StringReader、StringWriter、StringBufferInputStream。
(3)Pipe管道流。 實現管道的輸入和輸出(進程間通信): PipedReader與PipedWriter、PipedInputStream與PipedOutputStream。
2.2 節點流執行的圖示

 


3. 處理流
3.1 處理流的類型

 


- (1)Buffering緩沖流:在讀入或寫出時,對數據進行緩存,以減少I/O的次數:BufferedReader與BufferedWriter、BufferedInputStream與BufferedOutputStream。
- (2)Filtering 濾流:在數據進行讀或寫時進行過濾:FilterReader與FilterWriter、FilterInputStream與FilterOutputStream。
- (3)Converting between Bytes and Characters 轉換流:按照一定的編碼/解碼標准將字節流轉換為字符流,或進行反向轉換(Stream到Reader):InputStreamReader、OutputStreamWriter。
- (4)Object Serialization 對象流 :ObjectInputStream、ObjectOutputStream。
- (5)DataConversion數據流: 按基本數據類型讀、寫(處理的數據是Java的基本類型(如布爾型,字節,整數和浮點數)):DataInputStream、DataOutputStream 。
- (6)Counting計數流: 在讀入數據時對行記數 :LineNumberReader、LineNumberInputStream。
- (7)Peeking Ahead預讀流: 通過緩存機制,進行預讀 :PushbackReader、PushbackInputStream。
- (8)Printing打印流: 包含方便的打印方法 :PrintWriter、PrintStream。

3.2 處理流執行的圖示

 


3.3 緩沖流
【1】對I/O進行緩沖是一種常見的性能優化,緩沖流為I/O流增加了內存緩沖區,增加緩沖區的兩個目的:
(1)允許Java的I/O一次不只操作一個字符,這樣提高䇖整個系統的性能;
(2)由於有緩沖區,使得在流上執行skip、mark和reset方法都成為可能。

【2】緩沖流:它是要“套接”在相應的節點流之上,對讀寫的數據提供了緩沖的功能,
提高了讀寫的效率,同時增加了一些新的方法。例如:BufferedReader中的readLine方法,
BufferedWriter中的newLine方法。

【3】J2SDK提供了4種緩存流,常用的構造方法為:

//字符輸入流
BufferedReader(Reader in)//創建一個32字節的緩沖區
BufferedReader(Reader in, int size)//size為自定義緩存區的大小

//字符輸出流
BufferedWriter(Writer out)
BufferedWriter(Writer out, int size)

//字節輸入流
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int size)

//字節輸出流
BufferedOutputStream(OutputStream in)
BufferedOutputStream(OutputStream in, int size)

 


【4】其他
(1)緩沖輸入流BufferedInputSTream除了支持read和skip方法意外,還支持其父類的mark和reset方法;
(2)BufferedReader提供了一種新的ReadLine方法用於讀取一行字符串(以\r或\n分隔);
(3)BufferedWriter提供了一種新的newLine方法用於寫入一個行分隔符;
(4)對於輸出的緩沖流,BufferedWriter和BufferedOutputStream,寫出的數據會先在內存中緩存,
使用flush方法將會使內存的數據立刻寫出。

示例1:

import java.io.*;
public class TestBufferStream1 {
  public static void main(String[] args) {
    try {
      FileInputStream fis = new FileInputStream(
          "d:\\JavaProject\\demo13\\ProcessingStream\\TestBufferStream1.java");
      BufferedInputStream bis = new BufferedInputStream(fis);
      int c = 0;
      System.out.println((char)bis.read());
      System.out.println((char)bis.read());
      bis.mark(100);/*在當前輸入流的當前位置上做一個標志,允許最多再讀入100個字節*/
      for(int i=0;i<=10 && (c=bis.read())!=-1;i++){
        System.out.print((char)c+" ");
      }
      System.out.println(); 
      bis.reset();/*把輸入指針返回到以前所做的標志處*/
      for(int i=0;i<=10 && (c=bis.read())!=-1;i++){
        System.out.print((char)c+" ");
      }
      bis.close();
    } catch (IOException e) {e.printStackTrace();}
  }
}

 


示例2:

import java.io.*;
public class TestBufferStream2
{
    public static void main(String[] args)
    {
    try{
    BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\JavaProject\\demo13\\BufferStream\\dat2.txt"));
    BufferedReader br = new BufferedReader(new FileReader("D:\\JavaProject\\demo13\\BufferStream\\dat2.txt"));
    String s = null;
    for(int i=0;i<10;i++)
    {
        s = String.valueOf(Math.random());//產生一個小於1的正的隨機數,並轉換成字符串形式
        bw.write(s);//把字符串s寫入到dat2.txt文件中
        bw.newLine();//寫入一個行分隔符
    }
    bw.flush();//使用flush方法將會使內存的數據立刻寫出

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

    }
}

 

3.4 轉換流
轉換流有兩種:
(1)InputStreamReader:將字節流轉換為字符流;
(2)OutputStreamWriter:將字符流轉換為字節流。
什么時候使用轉換流?由以下分析: 流對象很多,就要明確使用哪個流對象。

通過三點來完成: 
    1、明確數據的來源和數據到達的目的地。
                 來源:輸入流 [InputStream,Reader]。 
                 目的:輸出流 [OutputStream,Writer]。 
    2、操作的數據是否是純文本。  
                 是:字符流,使用Reader與Writer; 
                 否:字節流,使用InputStream與OutputStream。 
    3、明確要使用哪個具體的對象。 通過設備來進行區分: 
                 源設備:內存用數組,硬盤就加file,鍵盤用System.in; 
                 目的設備:內存用數組,硬盤就加file,鍵盤用System.out4、明確是否還需要其他額外功能:例如 
                (1)是否需要較高的效率,即是否需要使用緩沖區,是就加上Buffered;
                (2)是否需要轉換,是,就使用轉換流,InputStreamReader 和 OutputStreamWriter。

 

用一個例子簡單的說明: 將鍵盤錄入的數據保存到一個文件中,輸入“over”時表示錄入結束。 詳細分析:

源:從InputStream,Reader中選擇; 因為是鍵盤錄入的是純文本,所以使用Reader。 
設備:鍵盤,所以用System.in; 發現System.in是字節流的操作,與Reader(字符流)矛盾,
這時就要用到轉換流 InputStreamReader 。為了提高操作效率,使用緩沖技術,選擇BufferedReader。 

目的:從 OutputStream,Writer中選擇。 因為是文本文件,所以選擇Writer。 
設備:硬盤上,一個文件,選擇FileWriter。 為了提高操作效率,使用緩沖技術,選擇BufferedWriter。 

 

示例1:

import java.io.*; 
    class ReadinFile 
        { 
            public static void main(String[] args)throws IOException //這里為了方便閱讀,先不做異常處理。 
            { 
                BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in)); 
                BufferedWriter bufw=new BufferedWriter(new FileWriter("readin.txt")); 
                String line=null; 
                while((line=bufr.readLine())!=null) 
                { 
                    if("over".equals(line)) break; 
                    bufw.write(line); 
                    bufw.newLine(); 
                } 
                bufw.close(); 
                bufr.close(); 
            } 
        }

 


示例2:

import java.io.*;
public class TestTransForm 
{
    public static void main(String[] args) throws IOException //這里為了方便閱讀,先不做異常處理。 
    {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        OutputStreamWriter osw = new OutputStreamWriter(
                                 new FileOutputStream("D:\\JavaProject\\demo13\\TransStream\\TransForm.txt",true));
        BufferedWriter bw = new BufferedWriter(osw);
        String str = null;
        str = br.readLine();
        while(str != null)
        {
            if(str.equalsIgnoreCase("exit")) break;
            bw.write(str);
            bw.newLine();
            str = br.readLine();
        }
        br.close();
        bw.close();
    }
}

 


注意:
(1)構造方法:public FileOutputStream(String name,boolean append) throws FileNotFoundException
如果append為True,輸出字節流就寫入文件的末尾,而不是開頭(覆蓋原來的內容);
如果append為False,輸出字節流就寫入文件的開頭,即覆蓋原來的內容從文件開始處寫內容。
(2)構造方法:public FileOutputStream(String name) throws FileNotFoundException
每次覆蓋原文件的內容,從文件開始處寫內容。
3.5 數據流——數據的存儲和數據恢復
數據流:DataInputStream和DataOutputStream
(0)DataInputStream和DataOutputStream是面向字節的,因此要使用InputStream和OutputStream。
(1)DataInputStream和DataOutputStream分別繼承InputStream和OutputStream,
它們屬於處理流,需要分別“套接”在InputStream和OutputStream類型的節點流上。
(2)DataInputStream和DataOutputStream提供了可以存取與機器無關的Java原始類數據(如:int,double等)的方法。
(3)DataInputStream和DataOutputStream的構造方法:

     DataInputStream(InputStream in)
     DataOutputStream(OutputStream out

 

示例1:

import java.io.*;
public class TestDataStream
{
    public static void main(String[] args) throws IOException
    {
        FileOutputStream fout = new FileOutputStream("D:/JavaProject/demo13_IO/DataStream/demo.txt",true);
        BufferedOutputStream bout = new BufferedOutputStream(fout);
        DataOutputStream dout = new DataOutputStream(bout);
        /*DataOutputStream,BufferedOutputStream,FileOutputStream這里使用了流棧。*/

        dout.writeInt(110);
        dout.writeUTF("hello,中國");
        dout.writeFloat(3.14f);
        dout.writeChar(97);/*97對應的是'a'*/
        dout.close();/*如果正在使用一個流棧,程序關閉最上面的一個流也就自動的關閉了棧中的所有底層流。*/

        FileInputStream fin = new FileInputStream("D:/JavaProject/demo13_IO/DataStream/demo.txt");
        BufferedInputStream bin = new BufferedInputStream(fin);
        DataInputStream din = new DataInputStream(bin);

        int i = din.readInt();
        String str = din.readUTF();
        float f = din.readFloat();
        char c = din.readChar();
        fin.close();/*如果正在使用一個流棧,程序關閉最上面的一個流也就自動的關閉了棧中的所有底層流。*/
        System.out.println("int:"+i+"\nString:"+str+"\nfloat:"+f+"\nchar:"+c);
    }

}

 

編譯,運行:

D:\JavaProject\demo13_IO\DataStream>javac TestDataStream.java

D:\JavaProject\demo13_IO\DataStream>java TestDataStream
int:110
String:hello,中國
float:3.14
char:a

 

注意:
int i = din.readInt();
String str = din.readUTF();
float f = din.readFloat();
char c = din.readChar();
/*此段代碼的順序不能亂,要保證先寫入的先讀出來的原則,否則會出現錯誤。
* 因此,我們在寫代碼的時候,我們必須:
* 要么為文件中的數據采用固定的格式;
* 要么將額外的信息保存到文件中,以便能夠對其進行解析以確定數據的尋訪位置。
*/
---------------------
作者:Joohong
來源:CSDN
原文:https://blog.csdn.net/jingzi123456789/article/details/72123937
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM