Java基礎之IO系列(二)

1.本文概述

本文講解IO系列有關字節流對象部分的內容。

字節流主要包含以下四個部分:

FileOutputStream
FileInputStream

BufferedOutputStream
BufferedinputStream

2.字節流的輸出操作

1.輸出流OutputStream

常用方法:

void close()
關閉此輸出流並釋放與此流有關的所有系統資源。
void flush()
刷新此輸出流並強制寫出所有緩衝的輸出字節。
void write(byte[] b)
將 b.length 個字節從指定的 byte 數組寫入此輸出流。
void write(byte[] b, int off, int len)
將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此輸出流。
abstract void write(int b)
將指定的字節寫入此輸出流。

說明:OutputStream是一個抽象類,無法直接實例化,因此一般使用其直接子類FileOutputStream。

2.文件輸出流FileOutputStream

構造方法:

FileOutputStream(File file)
創建一個向指定 File 對象表示的文件中寫入數據的文件輸出流。
FileOutputStream(File file, boolean append)
創建一個向指定 File 對象表示的文件中寫入數據的文件輸出流。如果爲append爲true,則將字節寫入文件末尾處,而不是覆蓋整個文件。
FileOutputStream(String name)
創建一個向具有指定名稱的文件中寫入數據的輸出文件流。
FileOutputStream(String name, boolean append)
創建一個向具有指定 name 的文件中寫入數據的輸出文件流。

常用方法:

void close()
關閉此文件輸出流並釋放與此流有關的所有系統資源。
void write(byte[] b)
將 b.length 個字節從指定 byte 數組寫入此文件輸出流中。
void write(byte[] b, int off, int len)
將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此文件輸出流。
void write(int b)
將指定字節寫入此文件輸出流。
void close()
關閉此輸出流並釋放與此流有關的所有系統資源。

需求描述:將字符串數據以字節流的形式寫入指定文件中

示例代碼:

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

public class FileOutputStreamDemo {

    public static void main(String[] args) {
        //聲明FileOutputStream對象
        FileOutputStream fos=null;
        try {
            //實例化FileOutputStream對象
            fos=new FileOutputStream("G:\\file_out_test.txt");
            //用於輸出的目標字符串
            String tarStr="這是通過字節流寫入文件的測試數據";
            //以字節流的輸出目標字符串
            fos.write(tarStr.getBytes());
            //刷新字節流緩存
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fos!=null)
                try {
                    //關閉字節流
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
}

程序運行結果

4.png


3.字節流的讀取操作

1.輸入流InputSteam

常用方法:

int available()
返回此輸入流下一個方法調用可以不受阻塞地從此輸入流讀取(或跳過)的估計字節數。
void close()
關閉此輸入流並釋放與該流關聯的所有系統資源。
abstract int read()
從輸入流中讀取數據的下一個字節。
int read(byte[] b)
從輸入流中讀取一定數量的字節,並將其存儲在緩衝區數組 b 中。
int read(byte[] b, int off, int len)
將輸入流中最多 len 個數據字節讀入 byte 數組。

long skip(long n)
跳過和丟棄此輸入流中數據的 n 個字節。

說明:FileInputStream是一個抽象類,無法直接實例化,因此一般使用其直接子類FileInputStream。

2.文件輸入流FileInputStream

構造方法:

FileInputStream(File file)
通過打開一個到實際文件的連接來創建一個 FileInputStream,該文件通過文件系統中的 File 對象 file 指定。
FileInputStream(String name)
通過打開一個到實際文件的連接來創建一個 FileInputStream,該文件通過文件系統中的路徑名 name 指定。

常用方法:

int available()
返回下一次對此輸入流調用的方法可以不受阻塞地從此輸入流讀取(或跳過)的估計剩餘字節數。
void close()
關閉此文件輸入流並釋放與此流有關的所有系統資源。
int read()
從此輸入流中讀取一個數據字節
int read(byte[] b)
從此輸入流中將最多 b.length 個字節的數據讀入一個 byte 數組中。
int read(byte[] b, int off, int len)
從此輸入流中將最多 len 個字節的數據讀入一個 byte 數組中。
long skip(long n)
從輸入流中跳過並丟棄 n 個字節的數據。

第一種方式:

    //部分代碼
    public static void main(String[] args) {
        //聲明FileInputStream對象
        FileInputStream fis=null;
        try {
            //實例化FileInputStream對象
            fis=new FileInputStream("G:\\file_out_test.txt");

            int ch=0;
            while((ch=fis.read())!=-1){
                //將獲取到的int型數據強轉爲char型輸出
                System.out.print((char)ch);
            }   

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally{
            if(fis!=null)
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

程序運行結果:

test:this file is used by OutputStream

說明:使用這種方式讀取數據,目標文件中不能存在中文,否則會出現亂碼。因爲無參構造方法每次只會讀取單個字節,而每個中文由兩個字節組成

第二種方式:

    //部分代碼
    public static void main(String[] args) {
        //聲明FileInputStream對象
        FileInputStream fis=null;
        try {
            //實例化FileInputStream對象
            fis=new FileInputStream("G:\\file_out_test.txt");
            //定義用於臨時存儲數據的字節數組,請區別於FileReader的字符數組
            byte[] bufArr=new byte[1024];

            //記錄讀取到的字符數組長度
            int len;
            while((len=fis.read(bufArr))!=-1){
                System.out.println(new String(bufArr,0,len));
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally{
            if(fis!=null)
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

程序運行結果:

test:this file is used by OutputStream
test:這裏使用了字節數組作爲緩衝區
tsst:所以我終於可以出現中文了

第三種方式-特有方式

示例代碼:

    //部分代碼
    public static void main(String[] args) {
        //聲明FileInputStream對象
        FileInputStream fis=null;
        try {   
            //實例化FileInputStream對象
            fis=new FileInputStream("G:\\file_out_test.txt");
            //建立和目標文件字節流大小一致的字節數組
            byte[] bufArr=new byte[fis.available()];
            //讀取字節流
            fis.read(bufArr);
            //將字節數組轉化爲字符串輸出
            System.out.println(new String(bufArr));

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally{
            if(fis!=null)
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

程序運行結果

test:this file is used by OutputStream
test:這裏使用了字節數組作爲緩衝區
tsst:所以我終於可以出現中文了

說明:這種方式只適用於文件較小的情況,因爲java虛擬機初始化時的默認內存僅爲64M

總結:考慮到實際開發中的效率要求,建議使用第二種方式。


4.拷貝圖片

需求描述:將G盤根目錄下的測試圖片複製到D盤

步驟:

1.用字節讀取流對象和圖片文件關聯
2.用字節寫入流對象創建一個圖片文件,用於存儲獲取到的圖片數據
3.通過循環讀寫,完成數據存儲
4.關閉資源

示例代碼:

    //部分代碼
    public static void main(String[] args) {
        //聲明字節輸入輸出流對象
        FileOutputStream fos=null;
        FileInputStream fis=null;

        try {
            //進行實例化
            fos=new FileOutputStream("D:\\test.png");
            fis=new FileInputStream("G:\\test.png");

            //臨時存儲數據的緩衝數組
            byte[] bufArr=new byte[1024];
            //記錄讀取的數據長度
            int len;
            while((len=fis.read(bufArr))!=-1){
                fos.write(bufArr, 0, len);
                fos.flush();//刷新流緩存
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fis!=null)
                try {
                    //關閉流
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            if(fos!=null)
                try {
                    //關閉流
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }       
    }

5.字節流的緩衝區

對應類:

BufferedOutputStream
BufferedInputStream

1.緩衝輸出流

構造方法:

BufferedOutputStream(OutputStream out)
創建一個新的緩衝輸出流,以將數據寫入指定的底層輸出流。
BufferedOutputStream(OutputStream out, int size)
創建一個新的緩衝輸出流,以將具有指定緩衝區大小的數據寫入指定的底層輸出流。

常用方法:

void flush()
刷新此緩衝的輸出流。
void write(byte[] b, int off, int len)
將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此緩衝的輸出流。
void write(int b)
將指定的字節寫入此緩衝的輸出流。
void close()
關閉此輸出流並釋放與此流有關的所有系統資源。
void write(byte[] b)
將 b.length 個字節寫入此輸出流。

2.緩衝輸入流

構造方法:

BufferedInputStream(InputStream in)
創建一個 BufferedInputStream 並保存其參數,即輸入流 in,以便將來使用。
BufferedInputStream(InputStream in, int size)
創建具有指定緩衝區大小的 BufferedInputStream 並保存其參數,即輸入流 in,以便將來使用。

常用方法:

int available()
返回可以從此輸入流讀取(或跳過)、且不受此輸入流接下來的方法調用阻塞的估計字節數。
void close()
關閉此輸入流並釋放與該流關聯的所有系統資源。
int read()
參見 InputStream 的 read 方法的常規協定。
int read(byte[] b)
從此輸入流中將 byte.length 個字節的數據讀入一個 byte 數組中。
int read(byte[] b, int off, int len)
從此字節輸入流中給定偏移量處開始將各字節讀取到指定的 byte 數組中。

long skip(long n)
跳過和丟棄此輸入流中數據的 n 個字節。

3.簡單應用

需求描述:將G盤的MP3文件通過緩衝字節流複製到D盤

示例代碼:

    //部分代碼
    public static void main(String[] args) {
        long start=System.currentTimeMillis();
        //聲明輸入輸出緩衝字節流對象
        BufferedInputStream bis=null;
        BufferedOutputStream bos=null;

        try {
            //實例化對象
            bis=new BufferedInputStream(new FileInputStream("G:\\test.mp3"));
            bos=new BufferedOutputStream(new FileOutputStream("D:\\test.mp3"));

            //寫入數據
            byte[] b=new byte[1024];
            int len=0;
            while((len=bis.read(b))!=-1){
                bos.write(b, 0, len);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally{
            if(bos!=null)
                try {
                    //關閉流
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            if(bis!=null)
                try {
                    //關閉流
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            long end=System.currentTimeMillis();
            System.out.println("消耗時間:"+(end-start)+"ms");
        }
    }

程序運行結果

消耗時間:13ms

說明:在本例中可以不使用flush進行刷新。並且因爲緩衝流的應用,文件的複製效率得到了大幅度提高

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章