21.Java語言緩衝流、轉換流、序列化反序列化、更改打印流

緩衝流

緩衝流的基本原理,是在創建流對象時,會創建一個內置的默認大小的(8k)緩衝區數組,通過緩衝區讀寫,減少系統IO次數,從而提高讀寫的效率。

1.字節緩衝流:

       1).輸出流:OutputStream

              |--FileOutputStream(基本流)

              |--FilterOutputStream

                     |--BufferedOutputStream(緩衝流)

       2).輸入流:InputStream

              |--FileInputStream(基本流)

              |--FilterInputStream

                     |--BufferedInputStream(緩衝流)

       3).構造方法:

BufferedInputStream(InputStream in) 創建一個 BufferedInputStream對象,參數是一個輸入流。InputStream是抽象

類,可以用子類對象

BufferedInputStream(Outputstream out) 創建一個 BufferedInputStream對象,參數是一個輸出流。Outputstream是抽

象類,可以用子類對象

4).代碼示例:

BufferedInputStream bin = new BufferedInputStream(new FileInputStream("demo.txt"));

BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("demo.txt"));

2.字符緩衝流:

       1).輸出流:Writer

              |--OutputStreamWriter(轉換流)

                     |--FileWriter(基本流)

              |--BufferedWriter(緩衝流)

              (特有方法:newLine():輸出一個換行符)

       2).輸入流:Reader

              |--InputStreamReader(轉換流)

                     |--FileReader(基本流)

              |--BufferedReader(緩衝流)

               (特有方法:readLine():讀取一行數據)轉換流

       3).構造方法:

       BufferedReader(Reader in) 創建使用默認大小的輸入緩衝區的 緩衝字符輸入流。

       BufferedWriter(Writer out) 創建使用默認大小的輸出緩衝區的緩衝字符輸出流。 

       4).代碼示例:

BufferedReader bin = new BufferedReader(new FileReader("demo.txt"));

BufferedWriter bout = new BufferedWriter(new FileWriter("demo.txt"));

3.緩衝流的使用_案例_文本排序:

public static void main(String[] args) throws IOException {

    //創建輸入輸出的緩衝流
    BufferedReader bin = new BufferedReader(new FileReader("sort.txt"));
    BufferedWriter bout = new BufferedWriter(new                
                                                 FileWriter("sort_allright.txt"));

    //Map存放序號和對應的句子
    Map<Integer,String> stringMap = new LinkedHashMap<>();

    //用緩衝流的特有方法,一次讀寫一行
    String s = null ;
    while ((s = bin.readLine()) != null) {
        //分割字符串
        String[] arr = s.split("\\.");
        stringMap.put(Integer.parseInt(arr[0]), arr[1]);
    }

    //按照序號遍歷Map中的內容並寫出
    for (int i = 1; i < stringMap.size(); i++) {
        bout.write(i + "." + stringMap.get(i));
        bout.newLine();
    }

    //關閉資源
    bin.close();
    bout.close();
}

轉換流

1.字符編碼和字符集:

字符編碼:

就是一套自然語言的字符與二進制數之間的對應規則。

計算機是以二進制存儲,按照某種規則,將字符存儲到計算機中,稱爲編碼

將存儲在計算機中的二進制數,按照某種規則解析顯示出來,稱爲解碼

字符集: 

常見的字符集(編碼表):記錄了字符和數字的映射關係。當計算機存儲“字符”時,實際存儲的是這個字符對應的數字的二進制。

       1.ASCII碼錶:最早的碼錶。記錄了128個字符,每個字符使用1個字節表示。

       2.中文的碼錶(GBxxxx)

              1).GB2312:早期的碼錶,裏面一共記錄了7000多個漢字;現在已經不使用了。

              2).GBK : 目前使用的碼錶。裏面一共記錄了2萬多個漢字,每個漢字使用2個字節表示;

              3).GB18030 : 未來要使用的碼錶。7萬多漢字。每個漢字使用1,2,3個字節表示;

     3.UTF-8碼錶:國際碼錶。有中文;字符采用1,2,3,4字節表示。每個中文使用:3個字節表示;

     4.Unicode碼錶:國際碼錶,有中文(3,4千),每個字符使用2個字節表示。Java就是支持Unicode碼錶的。

              5.ISO-8859-1碼錶:沒有中文。

編碼引出的問題:

       亂碼—解碼與編碼不一致

       例如:Windows中文系統中就是使用的GBK的編碼,在IDEA中默認的字符集是UTF-8,兩種編碼中漢字佔用的字節數不同,(UTF-8佔用三個字節)讀取時就會出現亂碼          解決:讀取時將編碼轉換成一致

2.轉換輸出流和轉換輸入流:

       1).轉換輸出流:

              構造方法:

              OutputStreamWriter(OutputStream in) : 創建一個用默認字符集的字符流。

OutputStreamWriter(OutputStream in, String charsetName) : 創建一個指定字符集的字符流。

public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
    OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream("demo.txt"));
    OutputStreamWriter out2 = new OutputStreamWriter(new FileOutputStream("demo.txt"),"GBK");
}

2).轉換輸入流:

構造方法:

InputStreamReader(InputStream in) : 創建一個使用默認字符集的字符流。

InputStreamReader(InputStream in, String charsetName) : 創建一個指定字符集的字符流。

public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
    InputStreamReader in1 = new InputStreamReader(new FileInputStream("demo.txt"));
    InputStreamReader in2 = new InputStreamReader(new FileInputStream("demo.txt"),"GBk");
}

3.轉換輸入輸出流使用:

IDEA默認的字符集是UTF-8,Windows默認的是GBK,爲了避免亂碼,使用GBK讀取文檔,然後用UTF-8輸出

public static void main(String[] args) throws IOException {

    //創建指定字符集轉換輸出輸入流,

    InputStreamReader in = new InputStreamReader(
                            new FileInputStream("demo.txt"),"GBK");
    OutputStreamWriter out = new OutputStreamWriter(
                            new FileOutputStream("demo_copy.txt"),"UTF-8");

    //按照字符讀取
    int b = 0;
    while ((b = in.read()) != -1) {
        out.write(b);
    }
    out.close();
    in.close();
}

如果讀取的輸出的編碼不一致就會亂碼

序列化流

序列化:

指將一個“對象連同屬性值”一起存儲在一個文件中,或者通過網絡傳輸,這個過程叫:序列化。

反序列化;

指將之前序列化的對象,再次讀取到程序中,並在內存中創建對象。

1.序列化流ObjectOutputStream類;

       構造方法:

public ObjectOutputStream(OutputStream out) : 創建一個指定OutputStream的ObjectOutputStream。

注意:被序列化的對象必須實現:java.io.Serializable(接口)

         此接口無任何抽象方法,這種接口叫:標記接口,表示開啓了某些功能。

public static void main(String[] args) throws IOException {
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("demo_Student.txt"));
    out.writeObject(new Student(1,"張三","男",23));
    out.close();
}

2.反序列化ObjectInputStream類:

       構造方法:

       public ObjectInputStream(InputStream in) : 創建一個指定InputStream的ObjectInputStream。

       注意:接收的Student必須是之前“序列化時”的那個包下的Student類型,不能是其它包下的,否則運行時異常。它必須是能夠找到class文件的類

public static void main(String[] args) throws IOException, ClassNotFoundException {

    ObjectInputStream in = new ObjectInputStream(new FileInputStream("demo_Student.txt"));

    //返回Object類型
    Student stu = (Student) in.readObject();
    System.out.println(stu);
    in.close();
}

3.版本號:

       Serializable 接口給需要序列化的類,提供了一個序列版本號。 serialVersionUID 該版本號的目的在於驗證序列化的對象和對應類是否版本匹配。

例如:private static final long serialVersionUID = 2;

如果沒有給定序列號,如果修改了序列化的類,再次反序列化的時候(沒有再次序列化)就會拋異常,因爲序列號不一樣了,如果給定了序列號,則不會拋異常

4.禁止屬性被序列化transient關鍵字

       用transient關鍵字修飾屬性,在序列化時該甦醒不會被序列化

當一個屬性被transient修飾,反序列化出來的值時屬性的默認值

1       張三       男       0//年齡屬性被禁止序列化,輸出爲0

5.序列化的使用_序列化集合:

 
public static void main(String[] args) throws IOException, ClassNotFoundException {

    //創建序列化的集合並初始化數據
    ArrayList<Student> stuList = new ArrayList<>();
    stuList.add(new Student(1,"張三","男",19));
    stuList.add(new Student(2,"張四","女",20));
    stuList.add(new Student(3,"張五","男",21));
    stuList.add(new Student(4,"張六","女",22));

    //創建序列化輸出流和反序列化輸入流
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("demo_xuliehuajihe.txt"));
    ObjectInputStream in = new ObjectInputStream(new FileInputStream("demo_xuliehuajihe.txt"));

    //序列化集合
    out.writeObject(stuList);

    //關閉資源
    out.close();

    //反序列化集合,並接受返回的集合
    ArrayList<Student> studentList = (ArrayList<Student>) in.readObject();

    //遍歷輸出反序列化返回的數據
    for (Student student : studentList) {
        System.out.println(student);
    }
    in.close();

}

 

打印流

1.字節打印流PrintStream類

       構造方法:

       public PrintStream(String fileName) 使用指定的文件名創建一個新的打印流。

2.改變打印流的方向:

System.out.println():向控制檯輸出數據,System.out就是:PrintStream類型;默認被指向:控制檯,想改變打印的方向,改變這個out就行

注意:

       Out是System類的一個成員屬性,所以可以用get/set方法訪問

輸出方法和控制檯一樣

使用示例:

public static void main(String[] args) throws FileNotFoundException {
    PrintStream ps = new PrintStream("demo.txt");
    System.setOut(ps);
    System.out.println("呵呵");
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章