1. 程式人生 > >緩衝流、轉換流、序列化流

緩衝流、轉換流、序列化流

一、緩衝流

1.1位元組緩衝流:

​ BufferedOutputStream: 位元組輸出緩衝流, 用來寫。
BufferedInputStream: 位元組輸入緩衝流, 用來讀。

​ 緩衝流內部有一個緩衝區陣列,所以他的效率是比較高的。其實緩衝流本身並不具備讀或者寫的功能,它其實是為其他流提供加速。

使用步驟:
    1. 建立緩衝流物件。
    2. 呼叫方法,讀或者寫(讀寫的方法和昨天學的FileOutputStream和FileInputStream一模一樣)
    3. 釋放資源。
緩衝流的構造方法:

​ BufferedInputStream(InputStream in): 需要傳遞一個位元組輸入流
BufferedOutputStream(OutputStream out) 需要傳遞一個位元組輸出流

public class Demo02BufferedStream {
    //使用緩衝流,一次讀寫一個位元組的方式複製檔案。
    public static void main(String[] args) throws IOException {
        //建立緩衝流輸入物件, 用來讀取
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("aa.jpg"));
        //建立緩衝流輸出物件, 用來寫
        BufferedOutputStream bos = new
BufferedOutputStream(new FileOutputStream("bb.jpg")); //開始複製,一次讀寫一個位元組。 long start = System.currentTimeMillis(); int i; while ((i = bis.read()) != -1) { bos.write(i); } long end = System.currentTimeMillis(); System.out.println(end -
start); //142 //釋放資源 bos.close(); bis.close(); } }
讀寫陣列複製檔案
/*
     使用緩衝流一次讀寫一個數組複製檔案

 */
public class Demo03BufferedStream {
    public static void main(String[] args) throws IOException {
        // 建立一個BufferedInputStream,用來讀
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("aa.jpg"));
        // 建立一個BufferedOutputStream, 用來寫
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bb.jpg"));

        long start = System.currentTimeMillis();
        //開始複製,一次讀寫一個數組
        byte[] bArr = new byte[1024 * 8];
        int len;
        while ((len = bis.read(bArr)) != -1) {
            bos.write(bArr, 0, len);
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start); //10

        //釋放資源
        bos.close();
        bis.close();

    }
}

1.2字元緩衝流:

​ BufferedReader:字元輸入緩衝流

​ BufferedWriter:字元輸出緩衝流

​ 字元緩衝流同樣自己也並不具備讀或者寫的功能, 他其實是為其他流提供加速。

字元緩衝流的基本使用:
1. 建立流物件。
2. 呼叫讀或者寫的方法(讀或者寫的方法和我們昨天學的FileReader和FileWriter一模一樣)
3. 釋放資源。
緩衝流的構造方法:

​ BufferedWriter(Writer out): 引數需要傳遞一個字元輸出流(FileWriter)
BufferedReader(Reader in): 引數需要傳遞一個位元組輸入流(FileReader)

字元緩衝流中特有的功能

​ 1.BufferedWriter中有一個特有的方法,可以寫一個跨平臺的換行符:
void newLine(): 實現一個跨平臺的換行符

​ 2.bufferedReader裡面也有一個特有的方法,可以一次讀取一行:
String readLine():一次讀取一行資料,並返回讀取到的這行, 如果讀取結束返回null

readLine不會讀取換行符,只會讀取換行符之前的內容

public class Demo04BufferedStream {
    public static void main(String[] args) throws IOException {
        method2();
    }

    /*
        使用BufferedReader 從檔案中讀資料
     */
    public static void method2() throws IOException {
        //建立字元緩衝輸入流物件
        BufferedReader br = new BufferedReader(new FileReader("file01.txt"));
        //開始讀
        char[] bArr = new char[1024];
        int len;
        while ((len = br.read(bArr)) != -1) {
            //處理讀取到的資料
            System.out.print(new String(bArr, 0, len));
        }
        //釋放資源
        br.close();
    }
    /*
        使用BufferedWriter向檔案中寫入資料
     */
    public static void method1() throws IOException {
        //建立緩衝輸出流物件
        BufferedWriter bw = new BufferedWriter(new FileWriter("file01.txt"));
        //呼叫方法,向檔案中寫入資料
        bw.write("請問今天你洗頭了嗎?");
        //釋放資源
        bw.close();
    }
}
讀取一行案例:
public class Demo05BufferedStream {
    public static void main(String[] args) throws IOException {
        method2();
    }

    /*
        String readLine():一次讀取一行資料,並返回讀取到的這行。 如果讀取結束返回null
     */
    public static void method2() throws IOException {
        //建立字元緩衝輸入流物件
        BufferedReader br = new BufferedReader(new FileReader("file02.txt"));
        //使用while迴圈改進下面的程式碼。
        //定義變數line儲存每次讀取到的這行資料
        String line;
        //開始迴圈依次讀取一行資料
        while ((line = br.readLine()) != null) {
            /*
                a). 呼叫readLine讀取一行資料
                b). 把讀取到的這行資料賦值給line
                c). 判斷line是否不等於null,如果不是,那麼表示讀取到了資料
             */
            System.out.println(line);
        }

        /*
        //讀取,一次讀取一行資料
        String line = br.readLine();
        System.out.println(line); //  你好

        line = br.readLine();
        System.out.println(line); //   我好

        line = br.readLine();
        System.out.println(line); //
        */
        //釋放資源
        br.close();
    }
    /*
        void newLine(): 實現一個跨平臺的換行符
     */
    public static void method1() throws IOException {
        //建立一個字元緩衝流物件
        BufferedWriter bw = new BufferedWriter(new FileWriter("file02.txt"));
        //呼叫方法,寫資料
        bw.write("你好");
        //呼叫 void newLine(): 實現一個跨平臺的換行符
        bw.newLine();
        bw.write("我好");
        bw.flush();
        bw.close();
    }
}

1.3恢復文字順序的案例

/*
    請將文字資訊恢復順序

    文字檔案的特點:
        1. 每一句話都是 由 序號.內容 組成的。
        2. 序號沒有重複。
        3. 每個序號對應一個內容。

    分析:
        1. 定義Map集合,存放每一句話的序號以及對應的內容。
        2. 建立BufferedReader,用來讀取。
        3. 開始讀取,一次讀取一行資料。
        4. 把讀取到的內容根據. 切割。
        5. 切割之後就得到了序號以及內容,然後新增到Map集合。
        6. 釋放資源。
        7. 定義BufferedWriter,用來寫
        8. 使用迴圈遍歷1-Map集合的大小。 然後拿到裡面的每一個數字(1-9之間的數字)
        9. 根據這個數字去Map集合中當做key獲取value。然後把鍵以及值進行拼接寫入到檔案。
        10. 釋放資源
 */
public class Demo06BufferedTest {
    public static void main(String[] args) throws IOException {
        //定義Map集合,存放每一句話的序號以及對應的內容。
        Map<Integer, String> map = new HashMap<>();
        //建立BufferedReader,用來讀取。
        BufferedReader br = new BufferedReader(new FileReader("出師表.txt"));
        //開始讀取,一次讀取一行資料。
        String line;
        while ((line = br.readLine()) != null) {
            //把讀取到的內容根據. 切割。
            //這個split根據正則表示式切割的。 而這個.是正則表示式的特殊字元,所以要根據.切割需要轉義
            //切割之後得到了一個字串陣列。 strArr[0]是 序號,strArr[1] 是內容。
            String[] strArr = line.split("\\.");
            //切割之後就得到了序號以及內容,然後新增到Map集合。
            Integer id = Integer.parseInt(strArr[0]);// 序號
            String content = strArr[1]; //內容
            map.put(id, content);
        }
        br.close();
        //定義BufferedWriter,用來寫
        BufferedWriter bw = new BufferedWriter(new FileWriter("outTeacherTable.txt"));
        //使用迴圈遍歷1-Map集合的大小。 然後拿到裡面的每一個數字(1-9之間的數字)
        for(int i = 1; i <= map.size(); i++) {//
            //把i當做key然後去Map集合獲取value
            String content = map.get(i);
            bw.write(i + "." + content);
            //換行
            bw.newLine();
            //重新整理
            bw.flush();
        }
        //釋放資源
        bw.close();
    }
}

二、轉換流

2.1字元編碼

​ 常見字元編碼:GBK–1/2個位元組、UTF-8–1/2/3/4個位元組、Unicode–2個位元組、ASCII --1個位元組、ISO-8859-1–2個位元組(拉丁文)。

2.2InputStreamReader

​ InputStreamReader是轉換流, 是位元組通向字元的橋樑。

​ InputStreamReader是用來讀取的。這個流可以指定編碼進行讀取。

使用步驟:
    1. 建立轉換流
    2. 呼叫方法,進行讀取。
    3. 釋放資源。
構造方法:

​ InputStreamReader(InputStream in): 是使用平臺預設的編碼方法進行讀取。
InputStreamReader(InputStream in, String charsetName): 是使用指定的編碼方式進行讀取。

注意: 其實轉換流本身也不具備讀或者寫的功能,轉換流做的工作其實是查碼錶轉碼的這樣的工作。

public class Demo02InputStreamReader {
    public static void main(String[] args) throws IOException {
		//readGBK();
        readUTF8();
    }


    	//讀取UTF-8的檔案
    public static void readUTF8() throws IOException {
        //建立轉換流物件
        //如果不指定編碼,預設採用的是平臺編碼,就是UTF-8
        //InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\file02-utf8.txt"));

        //指定UTF-8
        InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\file02-utf8.txt"), "utf8");
        int i;//定義i用來儲存讀取到的字元
        while((i = isr.read()) != -1) {
            System.out.print((char)i);
        }
        isr.close();
    }

    	//讀取GBK的檔案
    public static void readGBK() throws IOException {
        //建立InputStreamReader物件
        InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\file01-gbk.txt"), "gbk");
        //呼叫方法,進行讀取
        int i;//定義i用來儲存讀取到的字元
        while((i = isr.read()) != -1) {
            System.out.print((char)i);
        }
        isr.close();
    }
}

2.3OutputStreamWriter

​ OutputStreamWriter是轉換流, 是字元通向位元組的橋樑。
OutputStreamWriter 用來,並且可以指定編碼進行寫入。

使用步驟
1. 建立緩衝流物件
2. 呼叫方法,寫。
3. 釋放資源。
構造方法

​ OutputStreamWriter(OutputStream out) :是使用平臺預設的編碼。
OutputStreamWriter(OutputStream out, String charsetName): 使用指定的編碼 。

public class Demo03OutputStreamWriter {
    public static void main(String[] args) throws IOException {
        method2();
    }
//以UTF-8的格式寫
    public static void method2() throws IOException {
        //建立轉換流物件
        //使用的是平臺預設的utf-8編碼
        //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\file04-utf8.txt"));
        //指定utf-8編碼
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\file04-utf8.txt"), "utf-8");
        //呼叫write方法,寫資料
        osw.write("你好");
        //釋放資源
        osw.close();
    }
//寫GBK格式的資料
    public static void method1() throws IOException {
        //建立轉換流物件
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\file03-gbk.txt"), "gbk");
        //呼叫方法,寫
        osw.write("你好");
        //呼叫close方法,釋放資源
        osw.close();
    }
}

三、序列化Serializable

3.1序列化流

ObjectOutputStream 是序列化流, 可以將java程式中的物件寫入到檔案中。

步驟:
1. 建立序列化流物件。
2. 呼叫方法,寫物件。
3. 關流。
構造方法:

​ ObjectOutputStream(OutputStream out): 需要傳遞一個位元組輸出流。

寫物件的方法:

​ void writeObject(Object obj): 向檔案中寫物件。

注意: 要寫入到檔案的物件,一定要實現序列化介面(Serializable 介面)。

public class Demo01ObjectOutputStream {
    public static void main(String[] args) throws IOException {
        //建立一個序列化流物件
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file3-obj.txt"));
        //建立一個Person物件
        Person p = new Person("八神庵", 20);
        //呼叫writeObject把這個物件寫到檔案中國你
        oos.writeObject(p);
        //釋放資源
        oos.close();
    }
}

3.2反序列化流

ObjectInputStream 叫做反序列化流, 可以將檔案中的物件讀取到java程式中。

使用步驟
1. 建立ObjectInputStream物件。
2. 呼叫方法,讀取物件
3. 釋放資源。
構造方法:

​ ObjectInputStream(InputStream in):傳遞一個位元組輸入流。

讀取:

​ Object readObject(): 從檔案中讀取物件。

假如讀取的時候,要讀取的物件的類已經不存在了,就會報錯 ClassNotFoundException

public class Demo02ObjectInputStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1. 建立一個ObjectInputStream物件
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file3-obj.txt"));
        //2. 呼叫readObject方法,讀取物件
        Object obj = ois.readObject();
        Person p = (Person)obj;
        //3. 列印
        System.out.println(p.getName() + "--" + p.getAge());
        //釋放資源
        ois.close();
    }
}

3.3注意事項(版本號、序列號)

  • 被static修飾的成員不能被序列化, 被static修飾的成員屬於類不屬於物件。
  • 如果希望某個成員變數不會寫入到檔案,並且也不希望使用static關鍵字。那麼可以使用一個關鍵字這個關鍵字叫做transient ,這個transient意思是瞬態,被transient修飾的成員不能被序列化
public class Demo03StaticAndTransiend {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //writeObject();
        readObject();
    }
    //從檔案中讀物件
    public static void readObject() throws IOException, ClassNotFoundException {
        //建立一個反序列化流物件
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file4-obj.txt"));
        //呼叫readObject方法,從檔案中讀取物件
        Object obj = ois.readObject();
        Person p = (Person)obj;
        System.out.println(p.getName() + "-" + p.getAge());
        //釋放資源
        ois.close();
    }
    //向檔案中寫物件
    public static void writeObject() throws IOException {
        //建立一個序列化流物件
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file4-obj.txt"));
        //建立物件,並且把這個物件寫到檔案中
        oos.writeObject(new Person("牛郎", 12));
        //呼叫close方法,事項資源
        oos.close();
    }
}
  • 另外,當JVM反序列化物件時,能找到class檔案,但是class檔案在序列化物件之後發生了修改,那麼反序列化操作也會失敗,丟擲一個 InvalidClassException 異常。發生這個異常的原因如下:
    • 該類的序列版本號與從流中讀取的類描述符的版本號不匹配
    • 該類包含未知資料型別
    • 該類沒有可訪問的無引數構造方法
  • 解決方案
    • private static final long serialVersionUID = 1L
    • 此時表示定義了一個固定的版本號,不管這個類怎麼修改,版本號永遠是1

3.4序列化集合

需求:

  1. 將存有多個自定義物件的集合序列化操作,儲存到 list.txt 檔案中。
  2. 反序列化 list.txt ,並遍歷集合,列印物件資訊

分析:
1. 建立一個集合物件。
2. 新增學生物件。
3. 建立ObjectOutputStream序列化流,將物件(集合)寫入到檔案。
4. 釋放資源。
5. 建立ObjectInputStream,用來讀取。
6. 呼叫readObject,將檔案中的物件讀取出來。
7. 釋放資源

public class Demo05ObjectStreamTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //建立一個集合物件。
        ArrayList<Person> list = new ArrayList<>();
        //呼叫add方法,向集合中新增資料
        list.add(new Person("大冪冪", 18));
        list.add(new Person("小甜甜", 20));
        list.add(new Person("大甜甜", 40));
        //建立ObjectOutputStream序列化流,將物件(集合)寫入到檔案。
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file6-obj.txt"));
        //呼叫writeObject寫物件
        oos.writeObject(list);
        //釋放資源。
        oos.close();
        
        //建立ObjectInputStream,用來讀取。
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file6-obj.txt"));
        //呼叫readObject方法,進行讀取
        Object obj = ois.readObject();
        ArrayList<Person> newList = (ArrayList<Person>)obj;
        //遍歷
        for (Person person : newList) {
            System.out.println(person.getName() + "--" + person
            
           

相關推薦

緩衝轉換序列

1.緩衝流,也叫高效流,是對4個基本的FileXxx流的增強,所以也是4個流,按照資料型別分類: 位元組緩衝流:BufferedInputStream,BufferedOutputStream

緩衝轉換序列

一、緩衝流 1.1位元組緩衝流: ​ BufferedOutputStream: 位元組輸出緩衝流, 用來寫。 BufferedInputStream: 位元組輸入緩衝流, 用來讀。 ​ 緩衝流內部有一個緩衝區陣列,所以他的效率是比較高的。其實緩衝流本身並不具備

Java基礎----【緩衝轉換序列

緩衝流、轉換流、序列化流 主要內容 Properties 屬性集 轉換流 緩衝流 序列化流 列印流 第一章 屬性集 1.1 概述 java.util.Properties 繼承於Hashtable ,來表示一個持久的屬性集。它使用鍵值結構儲存資料,每個鍵及其

10緩沖轉換序列Files

unicode 英文 val edr pub 語言 dex 發生 cte 十、流 10.1 緩沖流 10.1.1 概述 緩沖流是對4個基本的FileXxx流的增強,所以也是4個流,按照數據類型進行分類

轉換序列列印commons-ioproperties

Java中傳輸最頻繁是字元但是傳輸開始用的是位元組流<不能看出傳輸的是啥>所以又有了字元流(底層為位元組流);   IO流的分類 |- 位元組流 - 位元組輸入流 InputStream 抽象類 -  FileInputStream 操作檔案的位元組輸入流 - 位元

java--Properties序列及反序列

ble his 持久化存儲 table dex this bubuko 描述符 信息 一、 Properties類 1、 Properties類介紹 Properties 類表示了一個持久的屬性集。Properties 可保存在流中或從流中加載。屬性列表中每個鍵及其對應值都

(java)IO物件(六)集合Properties類序列序列列印

【Properties特點】 /* * 集合物件Properties類特點: * 1. 繼承Hashtable,實現Map介面 * 2. 該集合無泛型,鍵值都是字串 * 3. 鍵值可以儲存到集合中,也可以儲存到持久化的裝置如硬碟、U盤、光碟上

Properties類序列與反序列

Properties類 Properties類介紹 特點: 1、Hashtable的子類,map集合中的方法都可以用。 2、該集合沒有泛型。鍵值都是字串。 3、它是一個可以持久化的屬性集。鍵值可以儲存到集合中,也可以儲存到持久化的裝置(硬碟、U盤、光碟)上。鍵值的來源也可以是持久化的裝置。 4、有和流

16IO (Properties序列打印CommonsIO)

獲取文件 ocs 字節打印流 解壓 遍歷數組 tostring tab 變量 tof Properties集合的特點 * A: Properties集合的特點 * a: Properties類介紹 * Properties 類表示了一個持久的屬性集。

IO(03)--序列列印

###序列化流 Java提供了一種**物件序列化**的機制,用一個位元組序列可以表示一個物件,該位元組序列包含該物件的資料、物件的型別和物件中儲存的屬性等資訊。位元組序列寫入到檔案中後,就相當於在檔案中儲存了一個物件資訊。 反之,該位元組序列還可以從檔案讀取出來,重構物件,對它進行反序列化。物件的資料、物

java第21天----轉換,標準,列印序列,Properties類

昨天知識總結 1.字元緩衝流 2.裝飾設計模式 3.介面卡設計模式 4.位元組流 5.位元組緩衝流 6.標準輸入流 流 轉換流 轉換流:本身是字元流 分類: InputStreamReader:從位元組輸入流到字元讀入流 OutputStreamWrit

Java IO-5 序列與反序列

str ride log getname file urn turn objects transient 建一個Person類 1 package demo05; 2 3 import java.io.Serializable; 4 5 public cla

Java——Properties集合,Object序列與反序列,打印,commons-IO文件工具類

都是 oos times odi store buffer src object 所有 一、properties集合 集合對象Properties類,繼承Hashtable,實現Map接口,可以和IO對象結合使用,實現數據的持久存儲。 p { margin-bottom:

IO--序列與反序列

ng- 對象 style 完成 alt 完整 寫入 配置 let IO流--序列化流與反序列化流: 序列化流:把對象當做流一樣寫入到文本文件中 ObjectOutputSream(); 反序列化流:把文本文件中的流對象還原成對象ObjectInputSream

java ->IO_序列與反序列

set final found class文件 ati 技術分享 保存到文件 back 序列化對象 序列化流與反序列化流 用於從流中讀取對象的操作流 ObjectInputStream 稱為 反序列化流 用於向流中寫入對象的操作流 ObjectOutputStream

【Redis錯誤】-Redis存取異常之序列問題

問題場景:因業務不斷擴充套件,實體類有較多的重複欄位,故要優化資料結構,從而優化系統性能,增加程式碼的可複用性。測試環境和預生產都沒有問題,到生產有部分欄位取不到數值,關了快取開關後,發現業務程式碼正常了,開啟快取就會出現各種null異常。 問題分析:Redis存進去的日誌正常,去的時候要麼少欄

序列與反序列

序列化是把物件特性儲存到物理介質上,反序列化是把儲存在物理介質上的物件取出還原成物件。 能被序列化的物件所屬的類必須實現Serializable介面。 1、物件序列化流ObjectOutputStream 構造方法: ObjectOutputStream(OutputStream out):建立寫入指

java序列序列與逆序列

package com.qianfeng.test; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.

Java筆記-I/O之物件序列

物件序列化流 物件序列化流基本介紹 使用工具:ObjectOutputStream,ObjectInputStream 介紹:將物件以檔案的形式儲存在硬碟中,使之能更方便的傳輸。 條件:必須實現Serializable介面(實現了這個介面,但

配置RedisTemplateJedisPoolConfigJedisConnectionFactory+自定義序列 (java方式)

java方式配置RedisTemplate   //spring注入ben    //@Bean(name = "redisTemplate") public RedisTemplate initRedisTemplate(){ JedisPoolConfig poolCo