Java IO可以分為兩大類,一個是位元組流對象,一個是字元流對象。位元組流對象讀取的是一個一個的位元組,即以位元組為單位進行讀取。而字元流對則是以字元為單位進行讀取。一般來說,字元流的效率要高些。但為什麼還要有位元組流對象呢?
這是因為流對象的表現形式有很多種。如果僅僅是文本資料,則單單用一個字元流對象就可以了。但是很多時候我們操作的是圖片、電影、mp3等這樣的資料,就只能用位元組流對象了。因為字元流對象在操作的過程中會用當前系統指定的編碼格式進行編碼和解碼。所以就不能操作那些非文本資料了。
要想把Java的IO對象全部說完,短時間內是不可能的。也沒有必要。那些很常見的一般大家都很熟悉了。也就沒必要再重複了。我就介紹幾個比較獨特,有特定適用環境的流對象吧。
PipedInputStream和PipedOutputStream
PipedInputStream
管道輸入資料流應該串連到管道輸出資料流;管道輸入資料流提供要寫入管道輸出資料流的所有資料位元組。通常,資料由某個線程從 PipedInputStream 對象讀取,並由其他線程將其寫入到相應的PipedOutputStream。不建議對這兩個對象嘗試使用單個線程,因為這樣可能死結線程。管道輸入資料流包含一個緩衝區,可在緩衝區限定的範圍內將讀操作和寫操作分離開。如果向串連管道輸出資料流提供資料位元組的線程不再存在,則認為該管道已損壞。--------Java文檔
PipedOutputStream
可以將管道輸出資料流串連到管道輸入資料流來建立通訊管道。管道輸出資料流是管道的發送端。通常,資料由某個線程寫入 PipedOutputStream 對象,並由其他線程從串連的PipedInputStream 讀取。不建議對這兩個對象嘗試使用單個線程,因為這樣可能會造成該線程死結。如果某個線程正從串連的管道輸入資料流中讀取資料位元組,但該線程不再處於活動狀態,則該管道被視為處於毀壞狀態。-----Java
文檔
注意到文檔中的一句話,“不建議對這兩個對象嘗試使用單個線程,因為這樣可能會造成該線程死結。”也就是說應該在多線程環境下使用這兩個對象。多線程下的話我們就可以利用它們進行線程間的通訊。PipedOutputStream 負責發送資訊,PipedInputStream 負責接收資訊,如果發送方的資訊沒有發送來的話,接收方就會處於阻塞狀態,一直等待。
Demo:
PipedInputStream
/** *Apr 5, 2013 *Copyright(c)JackWang *All rights reserve *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>*/package com.myjava.function;import java.io.IOException;import java.io.PipedInputStream;public class PipedIn implements Runnable{PipedInputStream pipIn = new PipedInputStream();/** * @param pipIn */public PipedIn(PipedInputStream pipIn) {this.pipIn = pipIn;}@Overridepublic void run() {byte[] buf = new byte[1024];try {int len = pipIn.read(buf);System.out.println(new String(buf,0,len));} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try {pipIn.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
PipedOutputStream
/** *Apr 5, 2013 *Copyright(c)JackWang *All rights reserve *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>*/package com.myjava.function;import java.io.IOException;import java.io.PipedOutputStream;public class PipedOut implements Runnable {PipedOutputStream pipOut = new PipedOutputStream();/** * @param pipOut */public PipedOut(PipedOutputStream pipOut) {this.pipOut = pipOut;}@Overridepublic void run() {String str = "嘿嘿,我來啦!!!";try {Thread.sleep(5000); //類比線程阻塞pipOut.write(str.getBytes());} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try {pipOut.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
Test
/** *Apr 5, 2013 *Copyright(c)JackWang *All rights reserve *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>*/package com.myjava.function;import java.io.IOException;import java.io.PipedInputStream;import java.io.PipedOutputStream;public class PipedIOTest {/** * @param args * @throws IOException */public static void main(String[] args) throws IOException {PipedInputStream in = new PipedInputStream(); //管道輸入資料流PipedOutputStream out = new PipedOutputStream(); //管道輸出資料流in.connect(out); //串連管道PipedIn pIn = new PipedIn(in);PipedOut pOut = new PipedOut(out);new Thread(pIn).start(); new Thread(pOut).start();}}
例子中採用Thread.sleep(5000)的方式類比線程阻塞。
------------------------------------------------------------------------------