Java(三)一篇文章讓你會用Java的io流

一、什麼是io流

JavaIO流,是一種計算機用語。主要是用於處理數據的傳輸。
——百度百科

流是指數據的流動,io流就是輸入輸出的流動。
在java中對數據的操作是用流的方式來實現的,數據不可能一瞬間就全部地從一個設備傳到另一個設備,所以只能採用一點一點流動的方式。
輸入流就是將其他地方的數據讀取到程序中輸出流就是將程序中的數據寫入到其他地方

二、io流的分類

1.四個抽象類

在java.io中提供了最重要的四個抽象類,InputStream(字節輸入流),OutputStream(字節輸出流),Reader(字符輸入流),Writer(字符輸出流)

一字符等於兩字節
根據輸出的數據單位,可以分爲兩類,字節流字符流

輸入
輸出
輸入
輸出
字節流
InputStream
OutputStream
字符流
Reader
Writer

還可以根據輸入或輸出,分爲輸入流輸出流
根據實現功能的不同,還可以分爲節點流處理流
節點流就是,從一個特定的節點讀取或者寫入數據。一看到節點就感覺好深奧,其實說白了就是從一個地方讀取或寫入數據,而這個地方可以是數據庫,控制檯,文件等。
處理流就是,代理節點流,實現一些其他的功能。像BufferedWriter,如果是普通的FileWriter,在執行寫操作時就就只能一個字符一個字符來寫,如果再套上一個BufferedWriter,就會有緩存的功能,寫的操作就會更加的快速了。

2.各種實現類

InputStream
節點流
FileOutputStream
PipedOutputStream
ByteArrayOutputStream
處理流
BufferedOutputStream
PrintStream
DataOutputStream
ObjectOutputStream
OutputStream
節點流
FileInputStream
PipedInputStream
ByteArrayInputStream
處理流
BufferedInputStream
SequenceInputStream
DataInputStream
ObjectInputStream
PrintStream
Reader
節點流
FileReader
PipedReader
CharArrayReader
處理流
BufferedReader
InputStreamReader
Writer
節點流
FileWriter
PipedWriter
CharArrayWriter
處理流
BufferedWriter
InputStreamWriter
PrintWriter

可能會有所遺漏,更加詳細的可以查看java官方的文檔。

三、如何使用

以FileInputStream和FileOutputStream爲例

1.代碼

package test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * @author xxj
 * io流測試
 */
public class IOTest {
    public static void main(String[] args) {
       //先打開一個文件
        File file= new File("C:\\Users\\Administrator\\Desktop\\test.txt");
        try{
            //先寫入數據
            FileOutputStream fileOutputStream=new FileOutputStream(file);
            fileOutputStream.write("ABCD".getBytes());
            fileOutputStream.close();
            //讀取數據
            FileInputStream fileInputStream=new FileInputStream(file);
            int i= 0;
            while ((i=fileInputStream.read())!=-1){
                System.out.println("通過fileInputStream讀取的數據:"+i);
                System.out.println("通過fileInputStream讀取的數據:"+(char)i);
                System.out.println("------");
            }
            fileInputStream.close();
        }catch (Exception e){}
    }
}

2.輸出結果

在這裏插入圖片描述
因爲我加了(char)所以自動做了ASCII碼錶的轉換
我的桌面也生成了test.txt文件,有興趣的拿代碼去跑一下吧。

3.解釋

可能有人會問,你這不對啊,你不是FileInputStream和FileOutputStream嗎,怎麼剛好每次讀取都是一個字母呢,不是一個字節嗎?
一個字節是八位,再看一下ASCII碼錶,裏面已經有上百個符號或字母了,肯定不能只用4bit來表示啦,最少也要用8bit,8bit最高可以表示256,所以這裏直接讀取就是單個字母來讀取的。

再以FileReader和FileWriter爲例

4.代碼

public class IOTest {
    public static void main(String[] args) {
        try{
            //先寫入
            File file=new File("C:\\Users\\Administrator\\Desktop\\writer.txt");
            FileWriter fileWriter=new FileWriter(file);
            fileWriter.write("ABC一二三");
            fileWriter.close();
            //讀取
            FileReader fileReader=new FileReader(file);
            int i=0;
            while ((i=fileReader.read())!=-1){
                System.out.println("通過reader讀取的數據:"+i);
                System.out.println("通過reader讀取的數據:"+(char)i);
                System.out.println("------");
            }
            fileReader.close();
        }catch (Exception e){}
    }
}

5. 輸出結果

在這裏插入圖片描述

6.解釋

我有個疑問,FileReader爲什麼可以讀字母,跟FileInputStream一樣,那爲什麼它會剛好可以只讀一箇中文又只讀到一個字母呢?
19968=0x4e00
writer.txt的16進制文件爲

4142 43 e4b8 80e4 ba8c e4b8 89

根本沒有4e00,那麼我們再轉化成二進制
(一)19968=100111000000000
(二)20108=100111010001100
(三)19977=100111000001001
0xe4b880e4ba8ce4b889=111001001011100010000000111001001011101010001100111001001011100010001001
我使用了String.replace()方法,發現e4b8 80e4 ba8c e4b8 89中並沒有包含一二三的二進制。

這裏就涉及到編碼了,常用的支持中文的編碼表是UTF-8,於是我將一二三拉進去查看進制轉換

在這裏插入圖片描述
這。真的是一套一套的。
到了這裏,也不是很清楚究竟是怎麼確認只讀一個字節還是讀一個字符

四、各種io流的特點

不同的io流使用起來是差不多的,只是細節上有些不同,具體的可以查查百度或者直接看每個實現類的源碼,畢竟它們都是分別繼承了InputStream(字節輸入流),OutputStream(字節輸出流),Reader(字符輸入流),Writer(字符輸出流),其中處理流是根據Filter···stream間接繼承的。

我稍微看了一下,想FileOutputStream最後的寫操作是帶有native修飾符的,又要查漏補缺了。

private native void writeBytes(byte b[], int off, int len, boolean append)
        throws IOException;

字節流和字符流的區別

  1. 字節流一次只能操作一個字節字符流可以操作兩個字節
  2. 字節流能夠處理任何文件類型,而字符流只能處理文本類型的文件

1.節點流

File流

字節:FileInputStream,FileOutputStream
字符:FileReader,FileWriter

特點

這些都是需要先創建一個File對象,然後才能使用的,而讀取或寫入操作都是在創建的File對象上做的。
只有一個區別,前兩個是字節流後兩個是字符流,如果需要讀取或寫入中文,就需要使用後兩個

Piped流

字節:PipedInputStream,PipedOutStream,
字符:PipedReader,PipedWriter
一般是多線程之間進行通信時使用的

特點

在使用這些流時,相比與File流,就不用先創建一個File對象,只需要跟普通的流一樣創建即可,但是在管道(Piped)相互通信前,需要使用connect方法將兩個管道連接起來

Piped流不需要使用文件作爲數據的載體。

字節/字符數組流

字節:ByteArrayInputStream,ByteArrayOutputStream
字符:CharArrayReader,CharArrayWriter

這四個流內部都會有一個數組,使用時是先向數組中存入數據,然後在從數組中讀取將數組的數據寫入到其他地方。

特點

Byte開頭的,就是隻能讀取或寫入字節。ByteArrayInputStream在創建時需要向構造方法傳遞一個參數(字節數組)ByteArrayOutputStream則在使用時,需要調用writeTo(某個流)這兩個流可以幫助我們先將數據存儲到緩存區,然後讀取寫入更加快速,開闢的緩存區是用來存儲字節數組的
CharArrayReader,CharArrayWriter和ByteArrayInputStream,ByteArrayOutputStream類似,只不過Char開頭的是讀寫字符,而Byte是讀寫字節,用法都一樣的。

2.處理流

處理流在使用的時候,是需要套上一個節點流,然後使用方法跟使用節點流差不多。

Buffered緩衝流

字節:BufferedInputStream,BufferedOutputStream
字符:BufferedReader,BufferedWriter

這四個流跟字節/字符流類似,它們內部也有一個數組作爲緩存區存在。但是,字節/字符數組流是將數據都緩存到數組中,並不會去刷新這個數組,想讀取或寫入都是從這個數組出發的;而Buffered緩衝流,這會有一個不會二次改變的數組(可以在構造方法中傳入size)一旦這個數組存滿了,就會將數組的數據全部讀出或寫入到其他地方,然後刷新數組

字節/字符數組流建議一次性用完就關閉

特點

在套用了其他節點流之後,使用的方法和節點流的使用方式差不多,但是在Buffered緩衝流寫入時還需要使用一個flush()方法,將緩存內部的數據全部寫入並且刷新緩存

轉化流

字符:InputStreamReader,OutputStreamWriter

特點

就是能夠將字節流轉換成字符流,在創建時,需要向構造方法傳遞一個字節流和字符集(默認爲GBK)使用的方法跟字符流的使用方法差不多。

數據流

字節:DataInputStream,DataOutputStream

特點

數據流是能夠將數據按照不同的類型寫入讀取也要按照相應的類型讀取。類似於寫入時,將數據裝入一個個不同類型的盒子了,讀取時要按照盒子的類型並且按照寫入的順序來讀取。

打印流

字節:PrintStream
字符:PrintWriter

特點

這兩個流並沒有對應的輸入流,使用這兩個的方法跟其他處理流差不多。在套上一個節點流後,就可以使用print()或println()直接寫入數據
有沒有覺得這兩個方法很熟悉,平時我們使用System.out.println()這個方法的內部其實也是使用PrintStream來實現的。

對象流

字節:ObjectInputStream,ObjectOutputStream

特點

這兩個流可以做一件事,就是我們要寫入或讀取的數據序列化,序列化就是將對象轉化成二進制數據。要使用這兩個流,第一步也是要套上一個節點流第二步就是在要序列化的類上實現Serializable接口,剩下的使用方法就跟普通的節點流差不多了。

五、總結

這些流真的是多,總結一下使用場景吧。
寫入或讀取都是文本類型有中文,就用字符流
寫入或讀取其他雜七雜八的文件類型沒有中文,就用字節流
要考慮線程通信,就用Piped流;要操作文件,就用File流;要將數據存在內存中,就用字節/字符數組流,沒有性能和功能要求,用這三個就夠了。
想要提高讀寫性能,就套個Buffered緩衝流;想要對規定數據格式,就套個數據流;想要使用方便或換行,就套個打印流;想要對對象序列化,就套個對象流

——————————————————————————————
如果本文章內容有問題,請直接評論或者私信我。
未經允許,不得轉載!

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