1. 程式人生 > 實用技巧 >位元組流(InputStream、OutputStream,FileInputStream,FileOutputStream)

位元組流(InputStream、OutputStream,FileInputStream,FileOutputStream)

位元組流
1.一切皆為位元組
在電腦中,一切的檔案資料(文字,圖片,視訊)都是二進位制進行儲存,是一個一個位元組,所以位元組流可以傳輸任何資料

2.位元組輸出流(OutputStream)---》切輸出流的父類,超類
Output輸出 stream位元組流
OutputStream為一個抽象類,需要子類繼承父類,繼承其方法,實現抽象方法
方法有:
void close()關閉此輸出流並釋放與此流相關聯的任何系統資源。
void flush() 重新整理此輸出流並強制任何緩衝的輸出位元組被寫出。
void write(byte[] b)將 b.length位元組從指定的位元組陣列寫入此輸出流。
void write(byte[] b, int off, int len) 從指定的位元組陣列寫入 len個位元組,從偏移 off開始輸出到此輸出流。

abstract void write(int b) 將指定的位元組寫入此輸出流。
常用子類:BufferedOutputStream , ByteArrayOutputStream , DataOutputStream , FilterOutputStream , InputStream , write(int)


2.1子類FileOutputStream------》將記憶體中的資料寫入到硬碟上的檔案
構造方法:
FileOutputStream(String name)
FileOutputStream(File file)
引數:
name:檔案路徑
file:指定檔案
構造方法的作用:
1.建立FileOutputStream物件

2.會根據構造方法中的引數(檔案/檔案路徑),建立一個空的檔案
3.將建立好的FileOutputStream物件指向建立的空檔案

寫入資料的原理(記憶體-->硬碟)
java程式--》jvm(java虛擬機器)--》OS(作業系統)--》OS呼叫寫資料的方法--》把資料寫入到檔案中去

位元組輸出流的使用步驟
1.建立一個FileOutputStream物件,構造方法中傳遞寫入資料的目的地
2.呼叫FileOutputStream物件中的write()方法,將資料寫入到檔案中
3.釋放資源(流的使用會佔用一定的記憶體,使用完畢要將記憶體清空,提高程式的效率)

寫資料的時候會將十進位制的整數轉化為二進位制的整數 fos.write(97) 97-->1100001

任意的文字編輯器(記事本、notepad++)在開啟檔案的時候,會查詢編碼表,把位元組轉化為字元表示
0-127查詢ASCII表 97--》a
其他值:查詢系統預設碼錶(中文系統GBK)

/*
* public void write(int b) throws IOException--一次只能寫一個位元組*/

/*
* public void write(byte b[]) throws IOException--一次寫多個位元組
* 注意:1.byte[] b 如果第一個位元組為正數(0-127),顯示時會查詢ASCII碼
* 2.如果第一個位元組為負數,那麼第一個位元組會和第二個位元組組成一箇中文顯示,查詢系統預設碼錶(GBK)*/

/*
* public void write(byte b[], int off, int len) throws IOException---一次寫字元陣列中特定長度位元組
* int off ---陣列的開始索引
* int len--寫入位元組的長度
*/

/*
* 寫入字元的方法,使用string類中的方法,將字元轉化為位元組陣列
* getBytes() 將字元轉化為位元組陣列*/

package iotest.byteIOtest;

import java.io.FileOutputStream;
import java.io.IOException;

public class TestFileOutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("C:\\test\\c.txt");
        /*
        * public void write(int b) throws IOException--一次只能寫一個位元組*/
        fos.write(98);
        fos.write(97);
//        byte[] b = {65,66,67,68,69};
        /*
        * public void write(byte b[]) throws IOException--一次寫多個位元組
        * 注意:1.byte[] b 如果第一個位元組為正數(0-127),顯示時會查詢ASCII碼
        *      2.如果第一個位元組為負數,那麼第一個位元組會和第二個位元組組成一箇中文顯示,查詢系統預設碼錶(GBK)*/
        byte[] b = {-65,-66,-67,68,69};
        fos.write(b);
        /*
        * public void write(byte b[], int off, int len) throws IOException---一次寫字元陣列中特定長度位元組
        * int off ---陣列的開始索引
        * int len--寫入位元組的長度
         */
        fos.write(b,0,2);
        /*
        * 寫入字元的方法,使用string類中的方法,將字元轉化為位元組陣列
        * getBytes() 將字元轉化為位元組陣列*/
        byte[] bytes = "你好".getBytes();
        System.out.println(bytes);
        fos.close();
    }
}

/*追加寫/續寫--用到兩個構造方法
* public FileOutputStream(File file, boolean append)
* public FileOutputStream(String name, boolean append)
* 其中append為追加續寫開關,
* 為true時,不覆蓋原始檔,繼續在檔案的末尾追加資料
* 為false時,建立的新檔案會覆蓋原始檔 */

/*寫換行:寫換行符合
* Windows:\r\n
* linux:/n
* mac:/r*/

package iotest.byteIOtest;

import java.io.FileOutputStream;
import java.io.IOException;

public class TestFileOutputStream02 {
    public static void main(String[] args) throws IOException {
        /*追加寫/續寫--用到兩個構造方法
        * public FileOutputStream(File file, boolean append)
        * public FileOutputStream(String name, boolean append)
        * 其中append為追加續寫開關,
        * 為true時,不覆蓋原始檔,繼續在檔案的末尾追加資料
        * 為false時,建立的新檔案會覆蓋原始檔 */
        /*寫換行:寫換行符合
        * Windows:\r\n
        * linux:/n
        * mac:/r*/
        FileOutputStream fos = new FileOutputStream("src\\iotest\\byteIOtest\\a.txt",true);
        for (int i = 0; i < 10; i++) {
            fos.write("你好".getBytes());
            fos.write("\r\n".getBytes());
        }

        fos.close();
    }
}

3.位元組輸入流(InputStream)----》將硬碟上檔案的資料,讀取到記憶體中使用
InputStream是所有自己輸入流的超類(父類),都要繼承該類

讀取資料的原理:
java程式-->JVM--》OS--》OS讀取資料的方法--》讀取檔案資料

FileInputStream:
位元組輸入流的使用步驟(重點):
1.建立FileInputStream物件,構造方法中要繫結要讀取的資料來源
2.使用FileInputStream物件中的read方法,來讀取檔案(指標會指向檔案的第一個位元組,read方法執行後,指標會跳到下一個位元組)
3.釋放資源(close)


3.1一次讀取一個位元組的方法:


public int read() throws IOException---》讀取檔案中一個位元組,並返回讀取到的位元組

讀取檔案是一個重複的過程,可以迴圈優化
但不知迴圈次數,可用while迴圈
迴圈結束的條件是讀取到-1結束

package iotest.byteIOtest;

import java.io.FileInputStream;
import java.io.IOException;

public class TestFileInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("src\\iotest\\byteIOtest\\a.txt");
//        int read = fis.read();
//        System.out.println(read);
        int len =0;
        while ((len = fis.read()) != -1) {
            System.out.println((char) len);
        }
        fis.close();
    }
}

3.2一次讀取多個位元組的方法:


public int read(byte b[])---》一次讀取多個位元組,放到位元組陣列b內,並返回這次讀取到的位元組個數

byte b[]:起緩衝作用,儲存每次讀取到的多個位元組(陣列的長度一般定義為1024(1kb)或者是1024的整數倍)

這兒也可以用while迴圈進行優化,迴圈結束的條件是讀取到-1結束

string的構造方法:
public String(byte bytes[]):將位元組陣列轉化為字串
public String(byte bytes[], int offset, int length) :將位元組陣列部分轉化為字串,offset為開始索引,length為長度,也就是要轉換的位元組個數

package iotest.byteIOtest;

import java.io.FileInputStream;
import java.io.IOException;

//位元組輸入流,一次讀取多個位元組的方法
public class TestFileInputStream02 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("src\\iotest\\byteIOtest\\a.txt");
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = fis.read(b)) != -1){
            System.out.println(len);
            System.out.println(new String(b,0,len));//如果這兒用new String(b),後面還有很多空格
        }
        fis.close();
    }
}

綜合使用:
檔案的複製(一讀一寫)
明確:資料來源(FileInputStream建立時的檔案地址)資料儲存的目的地(FileOutputStream建立時的檔案地址)
步驟:
1.建立FileInputStream物件,構造方法中要繫結要讀取的資料來源
2.建立FileOutputStream物件,構造方法中要繫結要寫入的資料來源
3.使用FileInputStream物件中read方法讀取檔案
4.使用FileOutputStream物件中write方法寫入檔案
5.釋放資源(先關閉寫入,後關閉讀,因為讀完不一定寫完,但寫完一定讀完)

package iotest.byteIOtest;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFile {
    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream("C:\\test\\MAH05314.MP4");
        FileOutputStream fos = new FileOutputStream("D:\\test\\copyView2.MP4");
       /*
       * 一個位元組一個位元組讀,面對較大檔案,效率較低*/
       /* int len = 0;
        while ((len = fis.read()) != -1){
            fos.write(len);
        }*/
        /*運用陣列緩衝,一個位元組陣列一個位元組陣列的讀,效率較高*/
        byte[] bytes = new byte[10240];
        int len = 0;
        while ((len = fis.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }
        //先關寫入流,再關讀取流
        fos.close();
        fis.close();
        long endTime = System.currentTimeMillis();
        System.out.println("檔案複製共用了"+(endTime-startTime)+"毫秒!");

    }
}