下面是用檔案輸入輸出流配合管道輸入輸出流完成檔案複制的功能。
發送方:檔案輸入流讀資料到管道輸出流。
接收方:管道輸入流讀資料到檔案輸出流。
package pipedCommunication;
import java.io.*;
public class Demo {
//發送線程
static class Sender implements Runnable {
PipedOutputStream pipedOutputStream = null;
public Sender(PipedOutputStream pipedOutputStream) {
this.pipedOutputStream = pipedOutputStream;
}
@Override
public void run() {
int len;
byte[] b = new byte[4];
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("C:\\Users\\PUBG\\Desktop\\test.txt"));) { //這裡可以改為從控制台讀入
while ((len = bis.read(b)) != -1) {
pipedOutputStream.write(b, 0, len);
}
pipedOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//接收線程
static class Receiver implements Runnable {
PipedInputStream pipedInputStream = null;
public Receiver(PipedInputStream pipedInputStream) {
this.pipedInputStream = pipedInputStream;
}
@Override
public void run() {
File file = new File("C:\\Users\\PUBG\\Desktop\\test1.txt");
if (file.exists())
file.delete();
byte[] b = new byte[6];
int len;
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
while ((len = pipedInputStream.read(b)) != -1) { //流中不存在資料時會阻塞
byte[] b1 = new byte[len];//拷貝一份一次讀取的資料
for (int i = 0; i < len; i++) {
b1[i] = b[i];
}
System.out.println("寫入檔案: " + new String(b1, "GBK"));
bos.write(b, 0, len);
}
pipedInputStream.close();
System.out.println("寫入完畢");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
;
}
}
public static void main(String[] args) throws IOException, InterruptedException {
PipedInputStream pipedInputStream = new PipedInputStream();
PipedOutputStream pipedOutputStream = new PipedOutputStream();
pipedOutputStream.connect(pipedInputStream);// 也可以在構造方法裡連接配接PipedOutputStream pipedOutputStream=new PipedOutputStream(pipedInputStream);
Thread receiver = new Thread(new Receiver(pipedInputStream));
Thread sender = new Thread(new Sender(pipedOutputStream));
receiver.start();
sender.start();
}
}
運作結果:
在中文系統中記事本預設編碼為GBK,以預設編碼儲存檔案開頭則無BOM标志。由于在記事本中全部為漢字,一個漢字在GBK編碼中占兩個位元組,而在程式中發送和接收都是2的倍數,則每次讀取的資料都能轉為漢字顯示在控制台上。
在PipedInputStream緩沖區中無資料時,read()方法會阻塞,有資料才繼續讀,是以先啟動接收者線程後啟動發送者線程,程式一樣正常執行。
如果在發送線程中沒有關閉pipedOutputStream,在發送線程退出後,接收線程的pipedInputStream.read()方法會抛出異常,記得用完後關閉。
java.io.IOException: Write end dead at java.io.PipedInputStream.read(PipedInputStream.java:310) at java.io.PipedInputStream.read(PipedInputStream.java:377) at java.io.InputStream.read(InputStream.java:101) at pipedCommunication.Demo$Receiver.run(Demo.java:45) at java.lang.Thread.run(Thread.java:748)