IO 流詳細分析

IO 流是輸入輸出機制

輸入:表示讀取外部數據(網絡或者硬盤)流向內存的流叫輸入流。

輸出: 表示程序將流輸出到外部,這種從內存流出的流叫做輸出流。

輸入和輸出的概念都是以內存爲出發點。比如讀取文件,表面上分析好像是輸出流,但是從內存分析,應該是讀取文件中的內容流入內存,所以實際上是輸入流。搞清楚這一點其實最容易混淆的已經被解決了。

IO結構

字節流

字節流可以讀取字節,在創建緩存的時候採用byte[]
字節流又包括 InputStream 和 OutputStream 具體有包含很多子類,這裏拿其中我個人最常用的兩個爲例。

FileInputStream

從輸入流中讀取 b.length 個字節的數據,當所有的字節都被讀取到緩存區中會返回 -1

/**
 * Reads up to <code>b.length</code> bytes of data from this input
 * stream into an array of bytes. This method blocks until some input
 * is available.
 *
 * @param      b   the buffer into which the data is read.
 * @return     the total number of bytes read into the buffer, or
 *             <code>-1</code> if there is no more data because the end of
 *             the file has been reached.
 * @exception  IOException  if an I/O error occurs.
 */
public int read(byte b[]) throws IOException {
    return readBytes(b, 0, b.length);
}
FileOutputStream

從輸出流中獲取的字節流中 off 到 len 的字節。

/**
 * Writes <code>len</code> bytes from the specified byte array
 * starting at offset <code>off</code> to this file output stream.
 *
 * @param      b     the data.
 * @param      off   the start offset in the data.
 * @param      len   the number of bytes to write.
 * @exception  IOException  if an I/O error occurs.
 */
public void write(byte b[], int off, int len) throws IOException {
    writeBytes(b, off, len, append);
}
代碼實現
private static void readFile(String path) {
    if (StringUtils.isBlank(path)){
        System.out.println("未指定準確路徑!");
        return;
    }
    File file = new File(path); // 目的是創建一個file對象並且檢查path路徑是否正常
    File fileNew = new File("D:/file/1/test.txt");  // 將 file 的字節流 保存到 fileSave 文件中
    if (!file.exists()){
        System.out.println("路徑下未發現文件!");
        return;
    }
    try (FileInputStream fis = new FileInputStream(file);
         FileOutputStream fos = new FileOutputStream(fileNew);) { // 創建一個讀取文件的輸入流(將文件讀入內存所以是輸入流)
        byte[] b = new byte[2048];  // 定義讀取數據的緩衝區
        int n = 0;// 得到實際讀取到的字節數
        // 循環讀取,每次最多讀取b.length個字節數據
        while((n = fis.read(b))!=-1){ // 讀取 數組b 大小的字節 讀取完成後返回 -1
            // 把字節轉成String
            String s = new String(b, 0, n);
            System.out.println(s);
            fos.write(b, 0, n);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

字符流

字符流可以讀取字符,不能操作字節在創建緩存的時候採用char[]
字符流又包括 Reader 和 Writer 具體有包含很多子類,這裏同樣拿其中我個人最常用的爲例。

FileReader & FileWriter

FileReader 和 FileWriter 代碼上與 FileInputStream, FileOutputStream 操作方法上區別不大,而關鍵在於配合 BufferedReader 使用可以提高效率

BufferedReader & BufferedWriter

BufferedReader 之所以可以提高效率在於 BufferedReader 在初始化時候默認設置 8k 的緩存區,這樣減少了 IO 操作,優先從緩存區獲取。

BufferReader 構造方法如下

private static int defaultCharBufferSize = 8192;

/**
 * Creates a buffering character-input stream that uses a default-sized
 * input buffer.
 *
 * @param  in   A Reader
 */
public BufferedReader(Reader in) {
    this(in, defaultCharBufferSize);
}

/**
 * Creates a buffering character-input stream that uses an input buffer of
 * the specified size.
 *
 * @param  in   A Reader
 * @param  sz   Input-buffer size
 *
 * @exception  IllegalArgumentException  If {@code sz <= 0}
 */
public BufferedReader(Reader in, int sz) {
    super(in);
    if (sz <= 0)
        throw new IllegalArgumentException("Buffer size <= 0");
    this.in = in;
    cb = new char[sz];
    nextChar = nChars = 0;
}

BufferReader 還有一個非常好用的方法 readLine ,也就是說會讀取一行數據,但是通過源代碼可以知道並不會讀取回車或換行,所以實際寫入文件的時候需要添加換行。

/**
 * Reads a line of text.  A line is considered to be terminated by any one
 * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
 * followed immediately by a linefeed.
 *
 * @return     A String containing the contents of the line, not including
 *             any line-termination characters, or null if the end of the
 *             stream has been reached
 *
 * @exception  IOException  If an I/O error occurs
 *
 * @see java.nio.file.Files#readAllLines
 */
public String readLine() throws IOException {
    return readLine(false);
}
代碼實現
private static void readFileByBuffer(String path) {
    if (StringUtils.isBlank(path)){
        System.out.println("未指定準確路徑!");
        return;
    }
    File file = new File(path); // 目的是創建一個file對象並且檢查path路徑是否正常
    File fileNew = new File("D:/file/1/test.txt");  // 將 file 的字節流 保存到 fileSave 文件中
    if (!file.exists()){
        System.out.println("路徑下未發現文件!");
        return;
    }
    try (FileReader fr = new FileReader(file);
         FileWriter fw = new FileWriter(fileNew);
         BufferedReader br = new BufferedReader(fr);    // 創建使用默認大小的緩衝字符輸入流
         BufferedWriter bw = new BufferedWriter(fw)) {
        String s="";
        while((s=br.readLine())!=null)
        {
            System.out.println(s); //readLine 不會獲取換行和回車,所以這裏打印需要加上換行
            s = s+"\n";
            bw.write(s);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章