1. 程式人生 > 其它 >Java基礎IO流介紹之三——什麼是位元組過濾流、常用的位元組過濾流有哪些

Java基礎IO流介紹之三——什麼是位元組過濾流、常用的位元組過濾流有哪些

位元組流的過濾流

作用:為節點流增強功能的

1、位元組流的緩衝流(BufferedXXX)

1、概述

緩衝: 就是一個位元組陣列 
實現高效的原理: 本質就是減少對硬碟的訪問次數

2、構造方法

方法名 說明
BufferedOutputStream(OutputStream out) 建立位元組緩衝輸出流物件
BufferedInputStream(InputStream in) 建立位元組緩衝輸入流物件

3、高效原理(減少對硬碟的訪問的次數)

BufferedOutputStream高效的原理:在該型別中準備了一個數組,儲存位元組資訊.
當外界呼叫write方法想寫出一個位元組的時候,該物件直接將這個位元組儲存到了自己的陣列中,而不重新整理到檔案中。
一直到該陣列所有8192個位置全都佔滿,該物件才把這個陣列中的所有資料一次性寫出到目標檔案中。
如果最後一次迴圈過程中,沒有將陣列寫滿,最終在關閉流物件的時候,也會將該陣列中的資料重新整理到檔案中。

BufferedInputStream高效的原理:在該型別中準備了一個數組,儲存位元組資訊.
當外界呼叫read()方法想獲取一個位元組的時候,該物件從檔案中一次性讀取了8192個位元組到陣列中,只返回了第一個位元組給呼叫者。
將來呼叫者再次呼叫read方法時,當前物件就不需要再次訪問磁碟,只需要從陣列中取出一個位元組返回給呼叫者即可.
由於讀取的是陣列,所以速度非常快。
當8192個位元組全都讀取完成之後,再需要讀取一個位元組,就得讓該物件到檔案中讀取下一個8192個位元組了。

4、關於關流和重新整理流的區別

在呼叫 close() 方法關流的時候,在關閉之前會先進行重新整理的操作,但是關流之後此流物件就不可以再使用了.
重新整理 flush() 在呼叫的時候,會將緩衝區的資料重新整理到硬碟中, 呼叫之後,並不會使流物件關閉 後邊還可以繼續使用.在開發中還是建議 先重新整理 在關流 . 

5、關於過濾流中是否需要關閉節點流

只需要在程式碼中將過濾流關閉即可,關閉了過濾流其實已經關閉了節點流.

案例

//案例1:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;

public class Demo3 {
    public static void main(String[] args) throws  Exception{
        //建立一個File物件
        File file = new File("file/a.txt");

        // 建立 檔案位元組輸出流 ----> 節點流  ----> 涼水
        FileOutputStream fileOutputStream = new FileOutputStream(file);

        //通過節點流物件 建立過濾流 增強功能
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

        //使用 過濾流 進行資料的處理
        String s = "abcd";

        //fileOutputStream.write(s.getBytes());//不關閉流 直接寫入
        bufferedOutputStream.write(s.getBytes());//首先寫入到了 緩衝區(記憶體裡) 還沒有寫入硬碟

        //重新整理
        //bufferedOutputStream.flush();
        //關流
        bufferedOutputStream.close();
        fileOutputStream.close();
    }
}


//案例2: 
import java.io.*;

public class Demo3 {
    public static void main(String[] args) throws  Exception{
        //建立一個File物件
        File file = new File("file/a.txt");

        //建立 節點流
        FileInputStream fileInputStream = new FileInputStream(file);

        // 通過節點流 建立 過濾流的物件
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

        //使用 過濾流 處理 資料
        int read = bufferedInputStream.read();//讀取一個位元組 其實是讀取了一個位元組陣列長度的資料 但是隻返回第一個位元組
        System.out.println((char)read);

        int read1 = bufferedInputStream.read();//讀取的第二個位元組資料 直接從上邊的緩衝區陣列中 返回第二個位元組
        System.out.println((char)read1);

        //關流
        bufferedInputStream.close();
    }
}

2、PrintStream流

1、概述

PrintStream介紹:
	是OutputStream子類,是位元組流
	列印陣列時,如果是字元陣列,可以直接顯示陣列內容,是因為呼叫print(char[] ch)或println(char[] ch)
	列印其他陣列時,呼叫的是print(Object obj)或println(Object obj),因此列印的是陣列地址值。

2、構造方法

方法名 說明
PrintStream(File file) 建立具有指定檔案且不帶自動行重新整理的新列印流。
PrintStream(OutputStream out) 建立新的列印流。
PrintStream(String fileName) 建立具有指定檔名稱且不帶自動行重新整理的新列印流。

案例

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;

public class Demo4 {
    public static void main(String[] args) throws FileNotFoundException {
        //構造方法

//        File file= new File("file/a.txt");
//        PrintStream stream1 = new PrintStream(file);
//
//        FileOutputStream fileOutputStream = new FileOutputStream(file);
//        PrintStream stream2 = new PrintStream(fileOutputStream);

        PrintStream stream3 = new PrintStream("file/a.txt");

        //具有很多過載的  print方法
//        stream3.println(23);
//        stream3.println('a');
//        stream3.println(12.3);
//        stream3.println("abcdefg");

        //建立一個學生物件
//        Student s = new Student("劉洋",13);
//        stream3.println(s);//可以將 物件 toString方法生成的字串直接輸出到檔案中  物件的屬性資訊

        char[] chars = "adfsfsafdsafd".toCharArray();
        System.out.println(chars.toString());
        stream3.println(chars);
        //關流
        stream3.flush();
        stream3.close();

    }
}

class Student{
    String name;
    int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3、物件流

1、概述

ObjectOutputStream / ObjectInputStream 物件輸入輸出流

2、作用

可以實現物件的序列化和反序列化

序列化: 將記憶體中的物件資料寫入到持久化儲存裝置中的過程 叫做物件的序列化.
反序列化: 將持久化儲存裝置中的物件資料讀入到記憶體中的過程 叫做物件的反序列化.

3、構造方法

	ObjectInputStream(InputStream in)
建立從指定的InputStream讀取的ObjectInputStream。
	ObjectOutputStream(OutputStream out)
建立一個寫入指定的OutputStream的ObjectOutputStream。

4、常用方法

void	writeObject(Object obj)
將指定的物件寫入ObjectOutputStream。
int	read()
讀取一個位元組的資料。
Object	readObject()
從ObjectInputStream讀取一個物件。
//案例1:

import java.io.*;

public class Demo5 {
    public static void main(String[] args) throws Exception{
        File file = new File("file/d.txt");//二進位制的檔案
//        FileOutputStream fileOutputStream  = new FileOutputStream(file);//節點流
//
//        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
//
//        //功能增強了
//        int a = 8;
//        objectOutputStream.write(a);
//        objectOutputStream.close();
//        System.out.println("寫入完畢");

        //讀取 資料8
//        FileInputStream fileInputStream = new FileInputStream(file);
//        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
//        int i = objectInputStream.read();
//        i++;
//        System.out.println(i);
//        objectInputStream.close();

    }
}

//案例2: 
import java.awt.datatransfer.FlavorEvent;
import java.io.*;

public class Demo6 {
    public static void main(String[] args) throws  Exception{
        //建立一個物件
        Student student = new Student("李程",38);

        //實現序列化
        File file = new File("file/a.txt");
//
//        FileOutputStream fileOutputStream = new FileOutputStream(file);//節點流
//
//        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
//
//        //寫物件了
//        objectOutputStream.writeObject(student);
//
//        //關流
//        objectOutputStream.close();
        FileInputStream fileInputStream = new FileInputStream(file);
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

        Object o = objectInputStream.readObject();
        //向下轉型
        Student s1 = (Student) o;
        s1.name = "劉能";
        System.out.println(o);
    }
}

//案例3:
import java.io.*;

public class Demo7 {
    public static void main(String[] args) throws Exception{
        File file = new File("file/a.txt");
//        FileOutputStream fileOutputStream = new FileOutputStream(file);
//
//        //建立物件流
//        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
//
//        //建立一個物件
//        Student s1 = new Student("李程",12);
//
//        objectOutputStream.writeObject(s1);
//
//        //關流
//        objectOutputStream.close();
//        System.out.println("序列化完畢");

        //反序列化
        FileInputStream fileInputStream = new FileInputStream(file);
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

        Object o = objectInputStream.readObject();
        System.out.println(o);
        System.out.println("反序列化結束");

    }
}

5、注意事項

1. 實現物件序列化,必須要求這個物件所屬的類實現 Serializable 介面
2. 如果一個物件中的某個屬性的值不想被序列化,這個屬性需要使用transient 修飾
3. serialVersionUID:可以為序列化指定版本id.防止類修改後讀取資料的異常.
  格式為: private static final long serialVersionUID = 42L;
4.當一個自定義物件實現序列化時此時在類中存在自定義類型別的屬性時,屬性也要實現序列化介面.