天天看點

IO流(位元組流、字元流、緩沖流)流的分類

流的分類

按操作資料機關不同分為:位元組流(8bit)二進制檔案,字元流(按字元)

按資料流的流向不同分為:輸入流、輸出流

按流的角色不同分為:節點流,處理流/包裝流

抽象基類 位元組流 字元流
輸入流 InputStream Reader
輸出流 OutputStream Writer

位元組輸入流(InputStream )

相關子類

FileInputStream:檔案輸入流

BufferedInputStream:緩沖位元組輸入流

ObjectInputStream:對象位元組輸入流

FileInputStream檔案輸入流

以位元組形式處理流,主要是處理二進制檔案。

@Test
public void reader01() throws IOException {
    String url = "C:\\Users\\lenovo\\Desktop\\hello.txt"; //檔案位址
    int readData = 0;
    FileInputStream fileInputStream = null;
    try {
        fileInputStream = new FileInputStream(url); //建立流
        while ((readData = fileInputStream.read()) != -1) { // 數為-1時則表示讀取完
            System.out.print((char) readData);
        }
    } catch (IOException e) {
        log.error(e.getMessage());
    }  finally {
        fileInputStream.close(); // 關閉流
    }
}
           

上述代碼是進行單位元組進行讀取是以速度相對較慢,也可以指定一次讀取的位元組數量。

fileInputStream = new FileInputStream(url); //建立流
byte[] bytes = new byte[15]; //一次讀取的位元組數量
// 數為-1時則表示讀取完
// 如果讀取正常readData值為讀取字元數量
while ((readData = fileInputStream.read(bytes)) != -1) {
	System.out.print(new String(bytes, 0, readData));
}
           

位元組輸出流(OutputStream)

相關子類:FileOutputStream位元組輸入流

@Test
public void write01() throws IOException {
    FileOutputStream fileOutputStream = null;
    String url = "C:\\Users\\lenovo\\Desktop\\a.txt"; //檔案位址
    String text = "123456789"; //需要寫入的資料
    try {
        // new FileOutputStream(url)這種方式寫入檔案是覆寫的方式
        // new FileOutputStream(url, true);這種方式寫入檔案是追加的方式
        fileOutputStream = new FileOutputStream(url, true);
        // write(byte b[], int off, int len)
        // write(byte b[])
        fileOutputStream.write(text.getBytes(), 1, 4); //将檔案寫入
    } catch (FileNotFoundException e) {
        log.error(e.getMessage());
    } finally {
        fileOutputStream.close(); //關閉連接配接
    }
}
           

字元輸入流(FileWriter)

FileWriter常用方法

1、 new FileWriter(File/String):覆寫模式,相當于流的指針在首端

2、new FileWriter(File/String,trule):追加模式,相當于流的指針在尾端’

3、 write(int):寫入單個字元

4、write(char[]):寫入指定數組

5、write(char[],off,len):寫入指定數組的指定部分

6、write (string) :寫入整個字元串

7、write(string,off, len):寫入字元串的指定部分

注意!!!FileWriter使用後,必須要關閉(close)或重新整理(flush),否則寫入不到指定的檔案!

@Test
public void write() throws IOException {
    FileWriter fileWriter = null;
    String url = "C:\\Users\\lenovo\\Desktop\\note.txt"; //檔案位址
    try {
        String text = "風雨過後,能見彩虹。";//寫入檔案内容
        fileWriter = new FileWriter(url);//開啟流
        //表示寫入位置0-5的字元
        fileWriter.write(text,0,5);
        System.out.println("程式結束");
    } catch (FileNotFoundException e) {
        log.error(e.getMessage());
    } finally {
        //關閉流
        if (fileWriter != null) {
            fileWriter.close();
        }
    }
}
           

字元輸入流(FileReader)

@Test
public void read01() throws Exception {
    FileReader fileReader = null;
    String Url = "C:\\Users\\lenovo\\Desktop\\hello.txt";//檔案位址
    int readData = 0;
    try {
        fileReader = new FileReader(Url); //啟動流
        char[] chars = new char[24]; //流每次讀取檔案大小
        //fileReader.read(chars)等于-1表示檔案讀取完成
        //readData的值為讀取的檔案大小
        //fileReader.read如果寫入讀取大小則每次讀取一個字元
        while ((readData = fileReader.read(chars)) != -1) {
            System.out.print(new String(chars, 0, readData));
        }
    } catch (FileNotFoundException e) {
        log.error(e.Message);
    } finally {
        //關閉流
        if (fileReader!= null) {
            fileReader.close();
        }
    }
}
           

緩沖流

緩沖流的作用就是對位元組、字元流更高效的讀寫。字元緩沖流(BufferedWriter、BufferedReader)和位元組緩沖流(BufferedInputStream、BufferedOutputStream)

緩沖流中使用了修飾模式。修飾模式大緻思想如下。

建立抽象類Reader_

public abstract class Reader_ {
    public void fileReader(){}

    public void stringReader(){}
}
           

分别建立FileReader_、StringReader_繼承Reader_并實作方法

public class StringReader_ extends Reader_{
    public void stringReader() {
        System.out.println("stringReader");
    }
}
           
public class FileReader_ extends Reader_{
    public void fileReader() {
        System.out.println("fileReader");
    }
}
           

在BufferedReader_中定義屬性Reader_,通過構造器傳入的reader屬性對FileReader、StringReader_中的方法調用

public class BufferedReader_ {
    private Reader_ reader;

    public BufferedReader_(Reader_ reader) {
        this.reader = reader;
    }

    public void fileReader() {
        reader.fileReader();
    }

    public void stringReader() {
        reader.stringReader();
    }
}
           

測試

public class demo {
    public static void main(String[] args) {
        BufferedReader_ bufferedReader_ = new BufferedReader_(new FileReader_());
        BufferedReader_ bufferedReader_1 = new BufferedReader_(new StringReader_());

        bufferedReader_.fileReader();
        bufferedReader_1.stringReader();
    }
}
           

字元緩沖流

注意:

1、BufferedWriter和BufferedReader是按照字元操作的

2、不要去操作二進制檔案(視訊、錄音等),不然可能造成檔案損壞

字元緩沖輸出流BufferedWriter

//檔案輸出流
@Test
public void write() throws IOException {
    // 檔案位址
    String url = "C:\\Users\\lenovo\\Desktop\\note.txt"; 
    // 将FileWriter轉換成BufferedWriter
    // new FileWriter(url, true)中的true表示以追加形式寫入,沒有true則為清空寫入
    BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(url, true));
    String text = "風雨過後";
    //寫入
    bufferedWriter.write(text);
    // 關閉流
    System.out.println("寫入成功");
    bufferedWriter.close();
}
           

字元緩沖輸入流BufferedReader

//檔案輸入流
public static void main(String[] args) throws Exception {
        String url = "C:\\Users\\lenovo\\Desktop\\note.txt";
        // 建立BufferedReader
        BufferedReader br = new BufferedReader(new FileReader(url));
        String s; //按行讀取
    	// s為null則表示讀取完
        while ((s = br.readLine()) != null) {
            System.out.println(s);
        }
        // 關閉流
        br.close();
    }
           

位元組緩沖流

想要操作二進制檔案則使用BufferedInputStream和BufferedOutputStream來操作。他們既可以操作二進制檔案也可以操作文本檔案。因為二進制是根本。

public class BufferedCopy02 {
    public static void main(String[] args) throws IOException {
        String url = "C:\\Users\\lenovo\\Desktop\\1527.wav";
        String newUrl = "C:\\Users\\lenovo\\Desktop\\海賊王.wav";
        //位元組緩沖輸入流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(url));
        //位元組緩沖輸出流
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(newUrl));
        //每次讀取位元組大小
        byte[] buffer = new byte[1024];
        int len;
        while ((len = bufferedInputStream.read(buffer))!= -1) { //讀取并寫入 -1讀取完成
            bufferedOutputStream.write(buffer, 0, len);
        }
        // 關閉流
        bufferedOutputStream.flush();
        bufferedInputStream.close();
    }
}
           

節點流/處理流

通過序列化和反序列化的方式将資料和資料類型儲存到檔案中。ObjectOutputStream輸出流和ObjectInputStream輸入流

注意事項和細節說明

1)讀寫順序要一緻

2)要求實作序列化或反序列化對象,需要實作 Serializable

3)序列化的類中建議添加SerialVersionUID,為了提高版本的相容性

4)序列化對象時,預設将裡面所有屬性都進行序列化,但除了static或transient修飾的成員

5)序列化對象時,要求裡面屬性的類型也需要實作序列化接口

6)序列化具備可繼承性,也就是如果某類已經實作了序列化,則它的所有子類也已經預設實作了序列化

ObjectOutputStream輸出流

public class ObjectOutputStream_ {
    public static void main(String[] args) throws IOException {
        String url = "C:\\Users\\lenovo\\Desktop\\data.dat"; //檔案位址
        ObjectOutputStream oos = null;
        try {
            // 建立流
            oos = new ObjectOutputStream(new FileOutputStream(url));
            //根據對應的類型寫入資料
            oos.writeChar(1);
            oos.writeDouble(1.1);
            oos.writeUTF("username");
            oos.writeObject(new Dog());
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            // 關閉流
            oos.close();
        }
    }
}
// Serializable序列化
class Dog implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
}
           

ObjectInputStream輸入流

@Slf4j
public class ObjectInputStream_ {
    public static void main(String[] args) throws IOException {
        String url = "C:\\Users\\lenovo\\Desktop\\data.dat"; //檔案位址
        ObjectInputStream ois = null;
        try {
            // 開啟輸入流
            ois = new ObjectInputStream(new FileInputStream(url));
            // 資料類型要與寫入資料類型一緻
            System.out.println(ois.readChar());
            System.out.println(ois.readDouble());
            System.out.println(ois.readUTF());
            System.out.println(ois.readObject());
        } catch (IOException | ClassNotFoundException e) {
            log.error("Error reading fileReader_", e.getMessage());
        }  finally {
            ois.close();
        }
    }
}