JAVA I/O流 字符流和字節流、節點流和處理流(包裝流、過濾流)、緩衝流

一、相關概念

I/O流: Input/Output Stream,文件輸入輸出流。

1、分類:

  • 輸入流 和 輸出流:(站在程序的角度) 根據讀寫操作/數據流動的方向區分。

    • 其中輸入流就是指讀取文件中的內容輸入到程序中的流,也就是讀文件。
    • 其中輸出流就是指將程序中的內容輸出到文件中的流,也就是寫文件。
  • 字節流 和 字符流:根據讀寫操作的基本單位分。

    • 參考: https://blog.csdn.net/yogima/article/details/78705411
    • 其中字節流就是指以字節爲基本單位進行讀寫的流,可以處理任何文件。字節(8位 )
    • 字符流就是指以字符(2個字節)爲基本單位進行讀寫的流,只能處理文本文件。字符(16位)。Reader和Writer
  • 數據傳輸方式:

    • 節點流(Node Stream 直接和文件打交道)
    • 包裝流(又稱處理流、過濾流、緩衝流)程序和文件之間有管道,不直接接觸。
  • 緩衝流:

    • 什麼是緩衝流:參考 https://www.cnblogs.com/aademeng/articles/10880511.html
    • 意義:在內存與硬盤之間創建一個大小合適的緩衝區,當內存和硬盤進行數據訪問時,能提高訪問硬盤的次數,提高效率。
      • 是一個包裝流,目的起緩衝作用.包括:
      • BufferedInputStream:字節輸入緩衝流
      • BufferedOutputStream:字節輸出緩衝流
      • BufferedReader:字符輸入緩衝流
      • BufferedWriter::字符輸出緩衝流
        字節流圖解
        字符流
        字符流套接

區別和聯繫

1、節點流和處理流

  • (1)節點流是低級流,直接跟數據源相接。

    • 處理流(也叫包裝流)把節點流包裝了一層,屬於修飾器設計模式,不會直接與數據源相連,通過處理流來包裝節點流既可以消除不同節點流的實現差異,也可以提供更方便的方法來完成輸入輸出。
  • (2)處理流的功能主要體現在以下兩個方面:

    • 1.性能的提高:主要以增加緩衝的方式來提高輸入輸出的效率。
    • 2.操作的便捷:處理流可能提供了一系列便捷的方法來一次輸入輸出大批量的內容,而不是輸入/輸出一個或多個水滴處理流可以嫁接在任何已存在的流的基礎上。
  • 節點流(Node Stream) :直接與原始數據存在的特定介質(如磁盤文件或其他外部設備、內存某區域或其他程序)打交道的流,在流的序列中離程序最遠。

  • 過濾流 (Filter Stream):使用其它的流作爲輸入源或輸出目的地,對流中的數據提供進一步處理的流。其他的流可以是節點流,也可以是另一種過濾流。過濾流不能單獨使用。

  • 一個輸入流鏈或輸出流鏈中一定有且只有一個節點流;可以沒有,也可以有多個過濾流。

2、字符流和字節流

代碼

  • 1、字節流: InputStream和OutputStream
    • InputStream
      InputStream是抽象類,不能直接用new InputStream()構造實例。 FileInputStream是InputStream的子類,可以生成實例。 FileInputStream有三個構造方法,最常用的構造方法如下:
      
      Public FileInputStream(String fileName) throws FileNotFoundException
      Public FileInputStream(File file) throws FileNotFoundException
      //fileName用來指定輸入文件名及其路徑,file是一個File對象
      
      InputStream類的read()方法:逐字節以二進制的原始方式讀取數據
      
      public int read();//讀入一個字節,-1表示無
      public int read(byte b[]);//返回讀入的字節數
      public int read(byte[] b,int off.int len);//返回從某個位置開始制定長度的字節數
      
    • OutputStream
      構造方法:
      OutputStream是抽象類,不能直接用new OutputStream()構造實例。 FileOutputStream是OutputStream的子類,可以生成實例。 FileOutputStream最常用的構造方法如下:
      
      Public FileOutputStream(String name) throws FileNotFoundException
      Public FileOutputStream(String name,boolean append) throws FileNotFoundException
      //Name用來指定輸入文件名及其路徑,append爲true時數據將添加到文件已有內容的末尾
      
      常用方法:
      //寫一個字節
      void write( int ) throws IOException 
      //關閉輸出流
      void close( ) throws IOException 
      //強行將緩衝區的數據寫到目的地。
      void flush( ) throws IOException 
      //寫一個字節數組
      void write(byte[ ] b) throws IOException 
          void write(byte[ ] b, int offset, int length ) throws IOException 
      
  • 利用字節流複製文件
import java.io.*;
class CopyAFile 
{
    public static void main(String[] args) 
    {
        InputStream in;
        OutputStream out;
        try
        {
            in=new FileInputStream("test.txt");
            out=new FileOutputStream("copyResult.txt");
//          out=new FileOutputStream("copyResult.txt",true);
            int aByte;
            aByte=in.read();
            while (aByte!=-1)
            {
                out.write(aByte);
                aByte=in.read();
            }
            in.close();
            out.close();
            System.out.println("文件複製完畢。test.txt已經複製到copyResult.txt中。");
        }
        catch(FileNotFoundException e)
        {
            System.out.println("當前目錄下文件test.txt不存在!");
        }
        catch(IOException e)
        {
            System.out.println("發生輸入輸出錯誤!");
        }
    }
}
  • 2、字符流: Reader和Writer

    • 字符(16位)流不一定對應兩個字節,要考慮到編碼問題。
    • 只能操作文本文件。
    Reader類讀取的是字符,而不是字節。 
    Reader類的重要方法read():
    
    public int read();//需要將int轉爲char
    public int read(char b[]);
    public int read(char[] b,int off,int len)
    
  • 3、濾流和節點流的套接:

InputStream in;
in=new BufferedInputStream(new FileInputStream("test.txt"));
BufferedReader in = new BufferedReader(new FileReader(file));

BufferedReader in2 = new BufferedReader(new inputStreamReader(new FileInputStream(file),"utf-8"));
s = in2.readLine();

套接流

嵌套的IO流關閉的問題

參考:https://blog.csdn.net/menghuanzhiming/article/details/77945822

  • 當然完全可以只關閉處理流,不用關閉節點流。處理流關閉的時候,會調用其處理的節點流的關閉方法

一般情況下是:

  • 先打開的後關閉,後打開的先關閉;
  • 另一種情況:看依賴關係,如果流a依賴流b,應該先關閉流a,再關閉流b
  • 例如處理流a依賴節點流b,應該先關閉處理流a,再關閉節點流b
  • 如果將節點流關閉以後再關閉處理流,會拋出IO異常;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章