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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

常见字节流

發(fā)布時(shí)間:2023/12/29 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 常见字节流 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

導(dǎo)航

  • FileInputStream/FileOutputStream
  • ByteArrayInputStream/ByteArrayOutputStream
  • BufferedInputStream/BufferedOutputStream
  • DataInputStream/DataOutputStream
  • ObjectInputStream/ObjectOutputStream
    • 序列化與反序列化

??以字節(jié)為單位獲取數(shù)據(jù)的流,稱為字節(jié)流,它們都繼承于InputStream/OutputStream抽象類。

??常用的字節(jié)流有:

  • FileInputStream/FileOutputStream,文件字節(jié)流(節(jié)點(diǎn)流)
  • ByteArrayInputStream/ByteArrayOutputStream,字節(jié)數(shù)組流(節(jié)點(diǎn)流)
  • BufferedInputStream/BufferedOutputStream,字節(jié)緩存流(處理流)
  • DataInputStream/DataOutputStream,數(shù)據(jù)字節(jié)流(處理流)
  • ObjectInputStream/ObjectOutputStream,對(duì)象流(處理流)

??下面分別介紹一下這五組字節(jié)流及用法。

FileInputStream/FileOutputStream

??FileInputStream/FileOutputStream是最常用的文件字節(jié)流,當(dāng)數(shù)據(jù)源為文件對(duì)象時(shí),選擇這個(gè)數(shù)據(jù)流進(jìn)行處理。我們可以通過(guò)構(gòu)造器快速了解它的操作數(shù)據(jù)類型:

public FileInputStream(File file)public FileOutputStream(File file)

??可以看到,這組數(shù)據(jù)流的操作對(duì)象為File類型。

??關(guān)于數(shù)據(jù)流的操作,總是分為四個(gè)步驟:

  • 1.指定數(shù)據(jù)源
  • 2.選擇合適的數(shù)據(jù)流
  • 3.進(jìn)行數(shù)據(jù)操作
  • 4.關(guān)閉流,釋放資源

??來(lái)一個(gè)文件的拷貝實(shí)例,了解其用法:

public class FileStream {public static void main(String[] args) {//1.指定數(shù)據(jù)源File in_scr = new File("a.txt"); // 輸入數(shù)據(jù)為文件File out_scr = new File("a-copy.txt"); // 輸出數(shù)據(jù)也為文件InputStream is = null;OutputStream os = null;try {//2.選擇合適的數(shù)據(jù)流is = new FileInputStream(in_scr);os = new FileOutputStream(out_scr);//3.進(jìn)行數(shù)據(jù)操作byte[] flush = new byte[1024]; //字節(jié)流,數(shù)據(jù)以字節(jié)數(shù)組為單位int len = -1;while( (len = is.read(flush)) != -1 ) { // for(int i=0;i<len;i++) { // System.out.println(flush[i]); 可以將輸入流直接打印出來(lái)觀察 // }os.write(flush,0,len);}os.flush(); //將緩存內(nèi)容輸出} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {//4.關(guān)閉流,釋放資源//先打開(kāi)的先關(guān)閉try {if(is != null) {is.close();}} catch (IOException e) {e.printStackTrace();}try {if(os != null) {os.close();}} catch (IOException e) {e.printStackTrace();}}}}

??需要注意的點(diǎn)有:

  • 1.flush為byte[]數(shù)組,與形參不同,數(shù)組傳入的是地址,所以在is.read(flush)方法中操作flush,外面的flush也會(huì)變換,read方法就是給flush賦值的一個(gè)方法,并且有返回值:讀取到的元素個(gè)數(shù),未讀到時(shí)返回-1。
  • 2.輸出流中是有緩存的,就是說(shuō)當(dāng)輸出流的數(shù)據(jù)量到達(dá)一定程度,才會(huì)輸出。所以在結(jié)尾,我們需要手動(dòng)將未到達(dá)緩存量的數(shù)據(jù)輸出,使用輸出流的flush()方法。

ByteArrayInputStream/ByteArrayOutputStream

??ByteArrayInputStream/ByteArrayOutputStream,字節(jié)數(shù)組流,也是一個(gè)常用的節(jié)點(diǎn)流。當(dāng)數(shù)據(jù)對(duì)象字節(jié)數(shù)組byte[ ]時(shí),使用這種流進(jìn)行操作。觀察一下它們的構(gòu)造器:

public ByteArrayInputStream(byte buf[])public ByteArrayOutputStream()

??可以看到,輸入流的操作對(duì)象未byte[ ]字節(jié)數(shù)組;輸出流無(wú)參數(shù),并不能直接將流中數(shù)據(jù)輸出為文件等,但ByteArrayOutputStream有toString()等方法,來(lái)方便對(duì)輸出流進(jìn)行操作。

??還是來(lái)一個(gè)文件的拷貝實(shí)例,了解其用法:

public class ByteArrayStream {public static void main(String[] args) {//1.指定數(shù)據(jù)源byte[] in_scr = new byte[] { -28, -67, -96, -26, -120, -111, -28, -69, -106 };//輸入數(shù)據(jù)ByteArrayInputStream bais = null;ByteArrayOutputStream baos = null;try {//2.選擇合適的數(shù)據(jù)流bais = new ByteArrayInputStream(in_scr);baos = new ByteArrayOutputStream();//3.進(jìn)行數(shù)據(jù)操作byte[] flush = new byte[1024];int len = -1;System.out.print("輸入流:");while ((len = bais.read(flush)) != -1) {for (int i = 0; i < len; i++) {System.out.print(flush[i]+","); //讀取輸入流}baos.write(flush, 0, len);}System.out.println();baos.flush(); //將緩存內(nèi)容輸出,到此,輸出流的數(shù)據(jù)寫(xiě)入已完成byte[] byteArray = baos.toByteArray(); //將輸入流轉(zhuǎn)換為字節(jié)數(shù)組System.out.print("輸出流:");for (byte b : byteArray) {System.out.print(b+",");}System.out.println();System.out.println(baos.size());//輸出流的元素個(gè)數(shù)System.out.println(baos.toString("UTF-8"));//注意,與byte[]的toString()不同} catch (IOException e) {e.printStackTrace();} finally {//4.關(guān)閉流,釋放資源try {if (bais != null) {bais.close();}} catch (IOException e) {e.printStackTrace();}try {if (baos != null) {baos.close();}} catch (IOException e) {e.printStackTrace();}}}} --------------------------------------------------- 輸出結(jié)果為: 輸入流:-28,-67,-96,-26,-120,-111,-28,-69,-106, 輸出流:-28,-67,-96,-26,-120,-111,-28,-69,-106, 9 你我他

BufferedInputStream/BufferedOutputStream

??BufferedInputStream/BufferedOutputStream,字節(jié)緩存流,是一種處理流,使用了裝飾設(shè)計(jì)模式,通過(guò)內(nèi)部緩存數(shù)組來(lái)提高操作流的效率。構(gòu)造器源碼:

public BufferedInputStream(InputStream in)public BufferedOutputStream(OutputStream out)

??可以看到BufferedInputStream/BufferedOutputStream只能對(duì)流進(jìn)行操作,而不能直接操作數(shù)據(jù),所以我們稱它為處理流。

??當(dāng)對(duì)文件或者其他數(shù)據(jù)源進(jìn)行頻繁的讀寫(xiě)操作時(shí),效率比較低,這時(shí)如果使用緩沖流就能夠更高效的讀寫(xiě)信息。因?yàn)榫彌_流是先將數(shù)據(jù)緩存起來(lái),然后當(dāng)緩存區(qū)存滿后或者手動(dòng)刷新時(shí)再一次性的讀取到程序或?qū)懭肽康牡亍?/p>

??緩存區(qū)的大小默認(rèn)是8192字節(jié)(8K,1024*8),也可以使用其它的構(gòu)造方法自己指定大小。

??因此,緩沖流還是很重要的,我們?cè)贗O操作時(shí)都可以加上緩沖流來(lái)提升性能。

??來(lái)一個(gè)文件復(fù)制的效率對(duì)比實(shí)例,了解用法與性能的提升:

public class BufferedStream {public static void main(String[] args) {// 使用緩沖字節(jié)流實(shí)現(xiàn)復(fù)制long time1 = System.currentTimeMillis();bufferedCopy("a.mp4", "a-copy1.mp4");long time2 = System.currentTimeMillis();System.out.println("緩沖字節(jié)流花費(fèi)的時(shí)間為:" + (time2 - time1));// 使用普通字節(jié)流實(shí)現(xiàn)復(fù)制long time3 = System.currentTimeMillis();fileCopy("a.mp4", "a-copy2.mp4");long time4 = System.currentTimeMillis();System.out.println("普通字節(jié)流花費(fèi)的時(shí)間為:" + (time4 - time3));}public static void bufferedCopy(String in_path, String out_path) {//1.指定數(shù)據(jù)源File in_scr = new File(in_path);File out_scr = new File(out_path);InputStream is = null;OutputStream os = null;try {//2.選擇合適的數(shù)據(jù)流is = new BufferedInputStream(new FileInputStream(in_scr));os = new BufferedOutputStream(new FileOutputStream(out_scr));//3.進(jìn)行數(shù)據(jù)操作byte[] flush = new byte[1024];int len = -1;while ((len = is.read(flush)) != -1) {os.write(flush, 0, len);}os.flush(); // 將緩存內(nèi)容輸出} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {//4.關(guān)閉流,釋放資源// 先打開(kāi)的先關(guān)閉try {if (is != null) {is.close();}} catch (IOException e) {e.printStackTrace();}try {if (os != null) {os.close();}} catch (IOException e) {e.printStackTrace();}}}public static void fileCopy(String in_path, String out_path) {//1.指定數(shù)據(jù)源File in_scr = new File(in_path);File out_scr = new File(out_path);InputStream is = null;OutputStream os = null;try {//2.選擇合適的數(shù)據(jù)流is = new FileInputStream(in_scr);os = new FileOutputStream(out_scr);//3.進(jìn)行數(shù)據(jù)操作byte[] flush = new byte[1024];int len = -1;while ((len = is.read(flush)) != -1) {os.write(flush, 0, len);}os.flush(); // 將緩存內(nèi)容輸出} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {//4.關(guān)閉流,釋放資源// 先打開(kāi)的先關(guān)閉try {if (is != null) {is.close();}} catch (IOException e) {e.printStackTrace();}try {if (os != null) {os.close();}} catch (IOException e) {e.printStackTrace();}}}} ----------------------------------------------- 輸出結(jié)果為: 緩沖字節(jié)流花費(fèi)的時(shí)間為:224 普通字節(jié)流花費(fèi)的時(shí)間為:972

DataInputStream/DataOutputStream

??DataInputStream/DataOutputStream,數(shù)據(jù)字節(jié)流(處理流),也是操作流的處理流,構(gòu)造器如下:

public DataInputStream(InputStream in)public DataOutputStream(OutputStream out)

?? 除了對(duì)流的包裝處理外,DataInputStream/DataOutputStream還可以實(shí)現(xiàn)直接對(duì)Java基礎(chǔ)數(shù)據(jù)類型(int、double、String等)直接進(jìn)行讀寫(xiě)操作。

?? 需要注意的是,使用數(shù)據(jù)流時(shí),讀取的順序一定要與寫(xiě)入的順序一致,否則不能正確讀取數(shù)據(jù)。

??先來(lái)一個(gè)對(duì)流的處理實(shí)例,還是復(fù)制為功能:

public class DataStream1 {public static void main(String[] args) {//1.指定數(shù)據(jù)源File in_scr = new File("a.txt");File out_scr = new File("a-copy.txt");DataInputStream dis = null;DataOutputStream dos = null;try {//2.選擇合適的數(shù)據(jù)流dis = new DataInputStream(new FileInputStream(in_scr));dos = new DataOutputStream(new FileOutputStream(out_scr));//3.進(jìn)行數(shù)據(jù)操作byte[] flush = new byte[1024];int len = -1;while( (len = dis.read(flush)) != -1 ) { // for(int i=0;i<len;i++) { // System.out.print(flush[i]); // }dos.write(flush, 0, len);}dos.flush();} catch (IOException e) {e.printStackTrace();} finally {//4.關(guān)閉流,釋放資源//先打開(kāi)的先關(guān)閉try {if(dis != null) {dis.close();}} catch (IOException e) {e.printStackTrace();}try {if(dos != null) {dos.close();}} catch (IOException e) {e.printStackTrace();}}}}

??再來(lái)一個(gè)直接讀寫(xiě)基本數(shù)據(jù)類型的實(shí)例:

public class DataStream2 {public static void main(String[] args) {//1.指定數(shù)據(jù)源File in_scr = new File("a.txt"); File out_scr = new File("a.txt");//輸入數(shù)據(jù)源與輸出數(shù)據(jù)源一致,先寫(xiě)再讀DataInputStream dis = null;DataOutputStream dos = null;try {//2.選擇合適的數(shù)據(jù)流dis = new DataInputStream(new FileInputStream(in_scr));dos = new DataOutputStream(new FileOutputStream(out_scr));//3.進(jìn)行數(shù)據(jù)操作//將如下數(shù)據(jù)寫(xiě)入到文件中dos.writeChar('a');dos.writeInt(10);dos.writeDouble(Math.random());dos.writeBoolean(true);dos.writeUTF("你我他");//Stirng類型//手動(dòng)刷新緩沖區(qū):將流中數(shù)據(jù)寫(xiě)入到文件中dos.flush();//直接讀取數(shù)據(jù):讀取的順序要與寫(xiě)入的順序一致,否則不能正確讀取數(shù)據(jù)。System.out.println("char: " + dis.readChar());System.out.println("int: " + dis.readInt());System.out.println("double: " + dis.readDouble());System.out.println("boolean: " + dis.readBoolean());System.out.println("String: " + dis.readUTF());} catch (IOException e) {e.printStackTrace();} finally {//4.關(guān)閉流,釋放資源//先打開(kāi)的先關(guān)閉try {if(dis != null) {dis.close();}} catch (IOException e) {e.printStackTrace();}try {if(dos != null) {dos.close();}} catch (IOException e) {e.printStackTrace();}}}} ----------------------------------------- 輸出結(jié)果為: char: a int: 10 double: 0.8627686668141537 boolean: true String: 你我他

ObjectInputStream/ObjectOutputStream

??DataInputStream/DataOutputStream可以直接讀寫(xiě)Java的基本數(shù)據(jù)類型。但Java中除了基本數(shù)據(jù)類型,還有引用數(shù)據(jù)類型,那么我們自己定義類,能不能也以類的方式放入IO流中呢?

??ObjectInputStream/ObjectOutputStream就是Java提供的操作對(duì)象的流,也叫對(duì)象流(處理流),構(gòu)造器源碼:

public ObjectInputStream(InputStream in)public ObjectOutputStream(OutputStream out)

??也是需要對(duì)流進(jìn)行操作,但使用它后,可以直接讀寫(xiě)任意的數(shù)據(jù)類型。

??需要注意的是,使用數(shù)據(jù)流時(shí),讀取的順序一定要與寫(xiě)入的順序一致,否則不能正確讀取數(shù)據(jù)。

序列化與反序列化

??需要注意的是,對(duì)象流中傳輸?shù)膶?duì)象必須支持進(jìn)行序列化與反序列化操作:

??當(dāng)兩個(gè)進(jìn)程遠(yuǎn)程通信時(shí),彼此可以發(fā)送各種類型的數(shù)據(jù)。 無(wú)論是何種類型的數(shù)據(jù),都會(huì)以二進(jìn)制序列的形式在網(wǎng)絡(luò)上傳送。比如,我們可以通過(guò)http協(xié)議發(fā)送字符串信息;我們也可以在網(wǎng)絡(luò)上直接發(fā)送Java對(duì)象。發(fā)送方需要把這個(gè)Java對(duì)象轉(zhuǎn)換為字節(jié)序列,才能在網(wǎng)絡(luò)上傳送;接收方則需要把字節(jié)序列再恢復(fù)為Java對(duì)象才能正常讀取。

??把Java對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程稱為對(duì)象的序列化。把字節(jié)序列恢復(fù)為Java對(duì)象的過(guò)程稱為對(duì)象的反序列化。

??對(duì)象序列化的作用有如下兩種:

  • 1.持久化: 把對(duì)象的字節(jié)序列永久地保存到硬盤(pán)上,通常存放在一個(gè)文件中,比如:休眠的實(shí)現(xiàn)。以后服務(wù)器session管理,hibernate將對(duì)象持久化實(shí)現(xiàn)。

  • 2.網(wǎng)絡(luò)通信:在網(wǎng)絡(luò)上傳送對(duì)象的字節(jié)序列。比如:服務(wù)器之間的數(shù)據(jù)通信、對(duì)象傳遞。

??只有實(shí)現(xiàn)了Serializable接口的類的對(duì)象才能被序列化。 Serializable接口是一個(gè)空接口,只起到標(biāo)記作用。

??序列化中需要注意的是:

  • 為了防止讀和寫(xiě)的序列化ID不一致,一般指定一個(gè)固定的序列化ID。
  • static屬性不參與序列化。
  • 對(duì)象中的某些屬性如果不想被序列化,使用transient修飾。

??來(lái)一個(gè)支持序列化類的實(shí)例:

//實(shí)現(xiàn)Serializable接口 class Student implements Serializable{// 添加序列化ID,它決定著是否能夠成功反序列化!private static final long serialVersionUID = 1L;private transient int num;private String name;private int age;public Student(int num,String name, int age) {super();this.num = num;this.name = name;this.age = age;}@Overridepublic String toString() {return "Student [num=" + num + ", name=" + name + ", age=" + age + "]";}}

??有了可以序列化的自定義類后,我們來(lái)試試使用ObjectInputStream/ObjectOutputStream流讀寫(xiě)它:

public class ObjectStream {public static void main(String[] args) {//1.指定數(shù)據(jù)源File in_scr = new File("a.txt");File out_scr = new File("a.txt"); //輸入數(shù)據(jù)源與輸出數(shù)據(jù)源一致,先寫(xiě)再讀ObjectInputStream ois = null;ObjectOutputStream oos = null;try {//2.選擇合適的數(shù)據(jù)流ois = new ObjectInputStream(new FileInputStream(in_scr));oos = new ObjectOutputStream(new FileOutputStream(out_scr));//3.進(jìn)行數(shù)據(jù)操作//將如下數(shù)據(jù)寫(xiě)入到文件中oos.writeChar('a');;oos.writeInt(10);oos.writeDouble(Math.random());oos.writeBoolean(true);oos.writeUTF("你我他");//實(shí)例化對(duì)象Student student = new Student(1,"小豬",18);oos.writeObject(student);//手動(dòng)刷新緩沖區(qū):將流中數(shù)據(jù)寫(xiě)入到文件中oos.flush();//直接讀取數(shù)據(jù):讀取的順序要與寫(xiě)入的順序一致,否則不能正確讀取數(shù)據(jù)。System.out.println("char: " + ois.readChar());System.out.println("int: " + ois.readInt());System.out.println("double: " + ois.readDouble());System.out.println("boolean: " + ois.readBoolean());System.out.println("String: " + ois.readUTF());System.out.println("Object: " + ois.readObject());} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {//4.關(guān)閉流,釋放資源//先打開(kāi)的先關(guān)閉try {if(oos != null) {oos.close();}} catch (IOException e) {e.printStackTrace();}try {if(ois != null) {ois.close();}} catch (IOException e) {e.printStackTrace();}}}} ---------------------------------------------------- 輸出結(jié)果為: char: a int: 10 double: 0.6826249100838067 boolean: true String: 你我他 Object: Student [num=0, name=小豬, age=18]

總結(jié)

以上是生活随笔為你收集整理的常见字节流的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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