java常用的字節流和字符流操作


在這裏插入圖片描述

前言

java 的 IO 流有很多類,常見常用的也就是字節流 InputStream 和 OutputStream 輸入輸出流,這是字節流兩個頂級父類(當然上面還有接口),還有 FileReader 和 FileWriter 輸入輸出流,這是字符流兩個頂級父類

輸入和輸出可以理解爲相對於內存或者屏幕來說的,從磁盤讀取到內存中是輸入,寫進磁盤則表示輸出。所以很好理解, InputStream 和 FileReader 用來做讀取數據操作,OutputStream 和 FileWriter 用來做把數據寫入磁盤的操作

下面這有一張菜鳥教程中的圖片,很清晰的展示了各個類之間的父子關係

img

字節流

常用的 OutputStream 和 InputStream 是輸出流和輸入流,二者都是抽象類,然後我們常用其中的 FileOutStream 和 FileInputStream,還有一個緩衝流 BufferedOutputStream 和 BufferedInputStream 是一個緩衝器,構造器分別接收 OutputStream 和 InputStream 的參數類型

字節流的追加就是在構造器的時候第二個參數傳入 true 即可,不傳默認是 false 就是完全覆蓋

OutputStream 字節輸出流

字節輸出流,下圖中我們知道 java.io 包中有如下這些字節輸出流的類,其中 OutputStream 是一個抽象類

其實絕大部分程序員最常用的也就是 FileOutputStream 和 BufferedOutputStream

在這裏插入圖片描述

小例子如下,其寫入文件磁盤只能接收 int 和 byte 類型,int 就是 ascall 碼對應的數字,字節就是一個字節,注意可不是 char 類型

如果我們不是用 buffer 也行,如果使用的話buffer.close()必加,不加的話 buffer 中的字節沒辦法存進磁盤中!!!

public class IOOperation {
    @Test
    public void fun() throws IOException {
        FileOutputStream stream = new FileOutputStream("src\\test\\java\\temp.txt");
        BufferedOutputStream buffer = new BufferedOutputStream(stream);
        buffer.write(new byte[]{'a', 'b', 'c'});
        buffer.close();
        stream.close();
    }
}

注意點

  • 如果使用了 buffer 注意要加``buffer.close()`否則不會將緩衝區的內容寫進磁盤!

InputStream 字節輸入流

字節輸入流,下圖中我們知道 java.io 包中有如下這些字節輸出流的類,其中 InputStream 是一個抽象類

其實絕大部分程序員最常用的也就是 FileInputStream 和 BufferedInputStream

在這裏插入圖片描述

public class IOOperation {
    @Test
    public void fun() throws IOException {
        FileInputStream stream = new FileInputStream("src\\test\\java\\temp.txt");
        BufferedInputStream buffer = new BufferedInputStream(stream);
        System.out.println(buffer.read());
        System.out.println(buffer.read());
        System.out.println(buffer.read());
        System.out.println(buffer.read());
        buffer.close();
        stream.close();
    }
}

注意點

  • 如果使用了 buffer 加不加``buffer.close()`都可以直接看到控制檯有正常輸出,這一點與輸出流是不同的
  • 使用 read 方法如果讀到沒有字節了,會直接返回 -1,read 方法返回 int 類型
  • 每次使用 read 方法之後,一個字節一個字節的往後讀

字符流

Writer 和 Reader 分別是字符輸出流和字符輸入流,二者都是抽象類,然後往下繼承的子類 OutputStreamWriter 和 InputStreamReader 都是實體類

字符流的追加就是在構造器的時候第二個參數傳入 true 即可,不傳默認是 false 就是完全覆蓋

Writer 字符輸出流

字符輸出流

其實一般情況下我們使用最多也就是 FileWriter 和 BufferedWriter

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-L998TSOZ-1593351677418)(C:\Users\石磊\Desktop\霍格沃茨培訓\學習筆記\框架優化\FileWriter.png)]

下面有個小例子,展示的是追加文件,先進入下一行,然後寫上 aaabbbccc

public class IOOperation {
    @Test
    public void fun() throws IOException {
        FileWriter writer = new FileWriter("src\\test\\java\\temp.txt", true);
        BufferedWriter buffer = new BufferedWriter(writer);
        buffer.newLine();
        buffer.write("aaa");
        buffer.append("bbb").append("ccc");
        buffer.close();
        writer.close();
    }
}

注意點

  • 字符流除了有 write 方法,還有 append 方法,write 方法沒有返回值且不可接受 null,但是 append 方法似乎就要靈活一些了,可以接收 null,寫入磁盤就是 null 的字符串,而且有返回值,返回就是字符流本身,因此可以不斷的.append("").append("")的形式
  • buffer 必加上 close,否則磁盤沒有內容

Reader 字符輸入流

字符輸入流

其實一般情況下我們使用最多也就是 FIleReader 和 BufferedReader

在這裏插入圖片描述

我們直接看下面的例子即可

public class IOOperation {
    @Test
    public void fun() throws IOException {
        FileReader reader = new FileReader("src\\test\\java\\temp.txt");
        BufferedReader buffer = new BufferedReader(reader);
        System.out.println(buffer.read());
        System.out.println(buffer.readLine());
        buffer.close();
        reader.close();
    }
}

注意點

  • 與字節流相似,輸入字符流在使用 buffer 時候沒有加 close 關掉 buffer 也一樣是可以把文件中的內容讀取到控制檯中的,相比輸出字符流就必須要加上 buffer 的 close 方法了
  • read 方法返回 int 型,也就是一個字符的 ascall 碼,readLine 方法可以返回當前位置後一整行的字符串類型
  • 如果 read 方法讀不到字符了它會返回 -1,如果 readLine 方法讀不到行了它會返回 null 的字符串

二者區別

字節流讀取字節,字符流讀取一個字符

字符流是可以設置編碼方式的

字符流更加靈活,推薦文本文件使用

使用場景

如果是操作文本文件,我建議直接使用字符流來操作,簡單便捷,若是圖片或者其他文件(電腦中的文件都是二進制形式文件,都可以使用字節流操作),我就推薦直接使用字節流來操作了

其他注意點

  • Write 輸出流的 flush() 操作是指,一般 IO 操作在有緩衝區的情況下,調用 close() 方法緩衝區纔會被輸出到磁盤中,如果直接執行 flush 可以在緩衝區沒有滿的時候手動輸出一次到磁盤

  • 字符流設置編碼方式可以通過 InputStreamReader 或者 OutputStreamWriter 的構造器來做,第二個參數傳輸編碼名字,這兩個類父類分別是 Reader 和 Writer,子類分別是 FileReader 和 FIleWriter。並且我查看了源碼發現如果不傳編碼方式,它會執行這段代碼Charset.defaultCharset().name(),它讀的是配置的語言編碼,或者說自己環境的語言編碼

  • 如果是中文,java 字節流也是可以讀取的但是讀取的東西可能就不好認識了,比如說一個“啊”讀取到屏幕上顯示 229 149 138

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