2015年1月3日 星期六

Java Inputstream與Outputstream



一、首先要了解Java如何以串流來抽象化輸入與輸出的概念,及Inputstream、Outputstream的架構,這樣一來無論是標準的輸出入、文檔的輸出入、網路的輸出入都可以用一致的操作來處理。

二、串流設計概念從應用程序的角度來看如果要將來源數據讀出,可用輸入串流將數據導到程序中,而若要將數據寫入目的端則可以使用輸出串流,就如下圖所示:

三、當我們有一個需求是來源與目的都不知道的情況下,可以設計一個通用的writeStreamingTo方法,這個方法接收了InputStream與OutputStream,將數據以Inputstream流入應用程序,再以Outputstream寫出檔案。

/**
     * 將來源數據利用輸入串流取出到應用程序,再利用輸出串流將檔案寫到目的,其中利用buffersize來控制緩衝區大小,並掌握進度。
     * @param in 輸入串流
     * @param out 輸出串流
     * @param bufferSize 緩衝區大小
     */
    private void writeStreamingTo(InputStream in,OutputStream out,int bufferSize){//待修改
        try {
            byte[] buffer = new byte[bufferSize];
            int len = 0;
            int totalBytes = in.available();
            int writedBytes = 0;
            System.out.println("Start Download.....");
            while ((len = in.read(buffer)) > 0) {
                writedBytes += len;
                out.write(buffer,0,len);
                System.out.println(String.format("%.2f%s",writedBytes / (double)totalBytes * 100,"%"));
            }
            in.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

四、Inputstream、Outputstream所提供的都是基本操作,如果想要為輸入輸出作加工處理,則可使用一些子類別,接下來將會介紹幾個常用的類別作為例子,但本質上並沒有改變,最後還是透過Inputstream、Outputstream進行真正的輸出入,故了解這兩個是比較重要的。
五、假設我們將某個檔案讀入並存到另一個檔案,則可以這麼使用。

FileInputStream in = new FileInputStream("來源路徑");
FileOutputStream out = new FileOutputStream ("目的路徑");
writeStreamingTo(in,out,1024);

六、假設我們要從HTTP服務器讀取某個網頁並另存新檔,那麼則可以考慮以下作法。

URLurl = new URL("路徑");
InputStream in = url.openStream();
OutputStream out= new FileOutputStream("目的路徑");
writeStreamingTo(in,out,1024);

七、關於第五點我們使用了FileInputStream與FileOutputStream,但是我們都知道檔案存取時,磁碟存取的速度遠低於記憶體,因此為了減少對磁碟的存取,可以一次讀入一定長度的資料,寫入時也是一次寫入一定長度的資料,這樣可以增加資料存取的效率,緩衝區的概念就因運而生,因此我們可以將第五點做個改寫,使用BufferedInputStream與BufferedOutputStream,因此我們開始將檔案資料流入應用程式時,是向緩衝區拿取資料,而非對來源直接作存取,當緩衝區沒資料時會自動去來源獲取,輸出時也是相同概念,並未直接將數據寫入磁碟,而是先寫入緩衝區,在由緩衝區放滿一定大小後回寫至磁碟。

byte[] data = new byte[1024]; 
BufferedInputStream in = new BufferedInputStream(new FileInputStream("myTest.txt"));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("myTest1.txt"));
while(in .read(data) != -1) { 
                bufferedOutputStream.write(data); 
 }
// 將緩衝區中的資料全部寫出 
bufferedOutputStream.flush();

沒有留言:

張貼留言