日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java IO5:管道流、对象流

發(fā)布時間:2023/12/31 java 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java IO5:管道流、对象流 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

前面的文章主要講了文件字符輸入流FileWriter、文件字符輸出流FileReader、文件字節(jié)輸出流FileOutputStream、文件字節(jié)輸入流FileInputStream,這些都是常見的流類。當(dāng)然除了這些流類之外,Java還提供了很多的流類給用戶使用,本文就看一下別的流。

?

管道流

管道流主要用于連接兩個線程的通信。管道流也分為字節(jié)流(PipedInputStream、PipedOutputStream)和字符流(PipedReader、PipedWriter)。比如一個PipedInputStream必須和一個PipedOutputStream對象進(jìn)行連接而產(chǎn)生一個通信管道,PipedOutputStream向管道中寫入數(shù)據(jù),PipedInputStream從管道中讀取數(shù)據(jù)。管道流的工作如下圖所示:

下面看一下管道流的用法。既然管道流的作用是用于線程間的通信,那么勢必有發(fā)送線程和接收線程,兩個線程通過管道流交互數(shù)據(jù)。首先寫一個發(fā)送數(shù)據(jù)的線程:

public class Sender implements Runnable {private PipedOutputStream out = new PipedOutputStream();public PipedOutputStream getOutputStream(){return out;}public void run(){String str = "Receiver, 你好!";try{out.write(str.getBytes()); // 向管道流中寫入數(shù)據(jù)(發(fā)送)out.close();} catch (IOException e){e.printStackTrace();}} }

用流寫數(shù)據(jù)的時候注意關(guān)注一下,該流是否支持直接寫String,不可以的話要用String的getBytes()方法獲取字符串的字節(jié)。既然有一個發(fā)送數(shù)據(jù)的線程了,接下來來一個接收數(shù)據(jù)的線程:

public class Receiver implements Runnable {private PipedInputStream in = new PipedInputStream();public PipedInputStream getInputStream(){return in;}public void run(){String s = null;byte b0[] = new byte[1024];try{int length = in.read(b0);if (-1 != length){s = new String(b0, 0 , length);System.out.println("收到了以下信息:" + s);}in.close();} catch (IOException e){e.printStackTrace();}} }

兩個線程都有了,寫一個main線程,利用管道輸出流的connect方法連接管道輸出流和管道輸入流:

public static void main(String[] args) {try{Sender sender = new Sender();Receiver receiver = new Receiver();Thread senderThread = new Thread(sender);Thread receiverThread = new Thread(receiver);PipedOutputStream out = sender.getOutputStream(); // 寫入PipedInputStream in = receiver.getInputStream(); // 讀出out.connect(in);// 將輸出發(fā)送到輸入senderThread.start();receiverThread.start();} catch (IOException e){e.printStackTrace();} }

輸出結(jié)果應(yīng)該很明顯了,大家都知道,接收線程接收到了來自發(fā)送線程通過管道流輸出流發(fā)送的數(shù)據(jù):

收到了以下信息:Receiver, 你好!

注意一下,PipedInputStream運(yùn)用的是一個1024字節(jié)固定大小的循環(huán)緩沖區(qū),寫入PipedOutputStream的數(shù)據(jù)實際上保存到了對應(yīng)的PipedInputStream的內(nèi)部緩沖區(qū)。PipedInputStream執(zhí)行讀操作時,讀取的數(shù)據(jù)實際上來自這個內(nèi)部緩沖區(qū)。如果對應(yīng)的PipedInputStream輸入緩沖區(qū)已滿,任何企圖寫入PipedOutputStream的線程都將被阻塞。而且這個寫操作線程將一直阻塞,直至出現(xiàn)讀取PipedInputStream的操作從緩沖區(qū)刪除數(shù)據(jù)。

這意味著,向PipedOutputStream寫入數(shù)據(jù)的線程不應(yīng)該是負(fù)責(zé)從對應(yīng)PipedInputStream讀取數(shù)據(jù)的唯一線程(所以這里開了兩個線程分別用于讀寫)。假定t線程試圖一次對PipedOutputStream的write()方法的調(diào)用中向?qū)?yīng)的PipedOutputStream寫入2000字節(jié)的數(shù)據(jù),在t線程阻塞之前,它最多能夠?qū)懭?024字節(jié)的數(shù)據(jù)(PipedInputStream內(nèi)部緩沖區(qū)的大小)。然而,一旦t被阻塞,讀取PipedInputStream的操作就再也不能出現(xiàn)了,因為t是唯一讀取PipedInputStream的線程,這樣,t線程已經(jīng)完全被阻塞。

?

對象流

序列化,在這篇文章中已經(jīng)講得比較清楚了,這一部分主要是再次簡單過一下對象流的知識而已。

Java中提供了ObjectInputStream、ObjectOutputStream這兩個類用于對象序列化操作,這兩個類是用于存儲和讀取對象的輸入輸出流類,只要把對象中的所有成員變量都存儲起來,就等于保存了這個對象,之后從保存的對象之中再將對象讀取進(jìn)來就可以繼續(xù)使用此對象。ObjectInputStream、ObjectOutputStream可以幫助開發(fā)者完成保存和讀取對象成員變量取值的過程,但要求讀寫或存儲的對象必須實現(xiàn)了Serializable接口。

看一下例子,先來一個實現(xiàn)了Serializable接口的實體類Person:

public class Person implements Serializable {/*** 序列化*/private static final long serialVersionUID = 7827863437931135333L;private transient String name;private int age;private final static String sex = "man";public Person(String name, int age){this.name = name;this.age = age;}public String toString(){return "姓名:" + this.name + ", 年齡:" + this.age + ", 性別:" + sex;} }

調(diào)用ObjectOutputStream和ObjectInputStream寫一個序列化和反序列化的方法,我現(xiàn)在D盤下沒有"serializable.txt":

public static void main(String[] args) throws Exception {File file = new File("D:/serializable.txt");serializable(file);deserializable(file); }// 序列化對象方法 public static void serializable(File file) throws Exception {OutputStream outputFile = new FileOutputStream(file);ObjectOutputStream oos = new ObjectOutputStream(outputFile);oos.writeObject(new Person("張三", 25));oos.close(); }// 反序列化對象方法 public static void deserializable(File file) throws Exception {InputStream inputFile = new FileInputStream(file);ObjectInputStream ois = new ObjectInputStream(inputFile);Person p = (Person)ois.readObject();System.out.println(p); }

現(xiàn)在運(yùn)行一下,D盤下多了一個"serializable.txt",文件里面的內(nèi)容是:

看到亂碼,因為序列化之后本身就是按照一定的二進(jìn)制格式組織的文件,這些二進(jìn)制格式不能被文本文件所識別,所以亂碼也是正常的。

當(dāng)然,控制臺上也是有輸出的:

姓名:null, 年齡:25, 性別:man

這證明了被transient修飾的成員變量不會被序列化。

轉(zhuǎn)載于:https://www.cnblogs.com/qypx520/p/5736553.html

總結(jié)

以上是生活随笔為你收集整理的Java IO5:管道流、对象流的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。