1. 程式人生 > >教你完全理解IO流裡的 read(),read(byte[]),read(byte[],int off,int len)以及write

教你完全理解IO流裡的 read(),read(byte[]),read(byte[],int off,int len)以及write

好的我們先來講它們的作用,然後再用程式碼來實現給大家看

  • read():

    1.從讀取流讀取的是一個一個位元組

    2.返回的是位元組的(0-255)內的位元組值

    3.讀一個下次就自動到下一個,如果碰到-1說明沒有值了.

  • read(byte[] bytes)

    1.從讀取流讀取一定數量的位元組,如果比如檔案總共是102個位元組

    2.我們定義的陣列長度是10,那麼預設前面10次都是讀取10個長度

    3.最後一次不夠十個,那麼讀取的是2個

    4.這十一次,每次都是放入10個長度的陣列.

  • read(byte[] bytes,int off ,int len)

    1.從讀取流讀取一定數量的位元組,如果比如檔案總共是102個位元組

    2.我們定義的陣列長度是10,但是這裡我們寫read(bytes,0,9)那麼每次往裡面新增的(將只會是9個長度),就要讀12次,最後一次放入3個.

    3.所以一般讀取流都不用這個而是用上一個方法:read(byte[]);

下面講解write

  • write(int i);

    直接往流寫入位元組形式的(0-255)int值.

  • write(byte[] bytes);

    往流裡邊寫入緩衝位元組陣列中的所有內容,不滿整個陣列長度的”空餘內容”也會加入,這個下面重點講,

  • write(byte[] bytes,int off,int len);

    1.這個是更嚴謹的寫法,在外部定義len,然後每次len(為的是最後一次的細節長度

    )都等於流往陣列中存放的長度

    2.如上述read(bytes),前面每次都放入十個,第十一次放入的是2個,如果用第二種write(bytes),將會寫入輸出流十一次,每次寫入十個長度,造成後面有8個空的,比原來的內容多了

    3.所以用write(byte[] bytes,int off,int len);就不會出現多出來的空的情況,因為最後一次len不同

下面是詳細的程式碼

public class Test{
    public static void main(String[] args) throws Exception {

        UseTimeTool.getInstance().start();

        FileInputStream fis = new
FileInputStream("D:\\1.mp3"); FileOutputStream fos = new FileOutputStream("D:\\1copy.mp3"); //(PS:一下3個大家分開來寫和測試,為了方便我都列出來了) /*--------------不使用緩衝--------------*/ //如果不緩衝,花了差不多14"秒" int len = -1; while ((len = fis.read()) != -1) { //這裡就不是長度的問題了,而是讀取的位元組"內容",讀到一個寫一個,相當慢. System.out.println("len : "+ len); fos.write(len); } /*--------------使用緩衝--------------*/ //緩衝方法複製歌曲用了不到20"毫秒" //建立一個長度為1024的位元組陣列,每次都讀取5kb,目的是快取,如果不用緩衝區,用fis.read(),就會效率低,一個一個讀位元組,緩衝區是一次讀5000個 byte[] bytes = new byte[1024*5]; //每次都是從讀取流中讀取(5k)長度的資料,然後再寫到檔案去(5k的)資料,注意,每次讀取read都會不同,是獲取到下一個,直到後面最後一個. while (fis.read(bytes)!=-1) { //write是最追加到檔案後面,所以直接每次添5K. fos.write(bytes); } /*--------------解釋len--------------*/ //告訴你為什麼用len byte[] bytes = new byte[1024*5]; int len = -1; //解釋這個fis.read(bytes)的意思:從讀取流"讀取陣列長度"的資料(列印len可知),並放入陣列 while ((len = fis.read(bytes,0,1024)) != -1) { //雖然陣列長度的*5,但是這裡我們設定了1024所以每次輸出1024 System.out.println("len : "+ len); //因為每次得到的是新的陣列,所以每次都是新陣列的"0-len" fos.write(bytes,0,len); } fis.close(); fos.close(); UseTimeTool.getInstance().stop(); } }

為了方便大家,也給大家一個統計時間的工具類

class UseTimeTool {
    private static UseTimeTool utt = new UseTimeTool();
    private UseTimeTool() {
    }
    public static UseTimeTool getInstance() {
        return utt;
    }
    private long start;
    public void start() {
        start = System.currentTimeMillis();
    }
    public void stop() {
        long end = System.currentTimeMillis();
        System.out.println("所用時間 : " + (end - start) + "毫秒");
    }
}

好了最後一個:len問題 最後多出陣列不滿的部分我特再寫一個出來給大家分析

首先,文字的內容是
這裡寫圖片描述

public class Test{
    public static void main(String[] args) throws Exception {

        UseTimeTool.getInstance().start();
        FileInputStream fis = new FileInputStream("D:\\a.txt");
        FileOutputStream fos = new FileOutputStream("D:\\acopy.txt");

不使用len:

byte[] bytes = new byte[1024*5];
        while (fis.read(bytes)!=-1) {
            fos.write(bytes);        
        }

得到的效果:
這裡寫圖片描述
發現後續後很多的空部分,所以說不嚴謹

使用len:

byte[] bytes = new byte[1024*5];
        int len = -1;
        while ((len = fis.read(bytes,0,1024)) != -1) {
            fos.write(bytes,0,len);
        }

得到的效果
這裡寫圖片描述
和原來一模一樣,講了那麼多就是希望能幫助大家真正的理解.