流是一個抽象的概念。當Java程序需要從數據源讀取數據時,會開啟一個到數據源的流。數據源可以是文件,內存或者網絡等。同樣,當程序需要輸出數 據到目的地時也一樣會開啟一個流,數據目的地也可以是文件、內存或者網絡等。流的創建是為了更方便地處理數據的輸入輸出。
流分為字節流和字符流。字節流也稱為原始數據,需要用戶讀入后進行相應的編碼轉換。而字節流的實現是基於自動轉換的,讀取數據時會把數據按照JVM的默認編碼自動轉換成字符。
字節流由InputStream和OutputStream處理,而字符流由Reader和Writer處理。Reader和Writer是Java后加入的處理類,出於讓數據的處理更方便的目的。
字節流處理概述:
對於字節流處理的類都繼承自InputStream和OutputStream這兩個抽象類。
InputStream提供的最重要的方法是:
- read();
- read(byte[] b) ;
- read(byte[] b, int off, int len) ;
- read();
- read(byte[] b) ;
- read(byte[] b, int off, int len) ;
read(); read(byte[] b) ; read(byte[] b, int off, int len) ;
用於從輸入流中讀取字節。
OutputStream提供的最重要的方法是:
- write(int b);
- write(byte[] b);
- write(byte[] b, int off, int len)
- write(int b);
- write(byte[] b);
- write(byte[] b, int off, int len)
write(int b); write(byte[] b); write(byte[] b, int off, int len)
用於將字節寫入輸出流。
字節流處理類概述:
字節流的處理類有很多,他們都繼承自InputStream或者OutputStream抽象類。
輸入流:
先談談輸入流,輸入流中跟數據源直接接觸的類有:FileInputStream和ByteArrayInputStream,他們分別實現了從文 件或者內存中的字節數組讀入數據到輸入流。
其他的輸入流處理類都是裝飾類(Decorator模式),下面對他們進行一下簡單介紹:
BufferedInputStream: 提供了緩沖功能。
DataInputStream: 允許應用程序以與機器無關方式從底層輸入流中讀取基本 Java 數據類型。應用程序可以使用數據輸出流寫入稍后由數據輸入流讀取的數據。
PipedInputStream: 允許以管道的方式來處理流。當連接到一個PipedOutputStream后,它會讀取后者輸出到管道的數據。
PushbackInputStream: 允許放回已經讀取的數據。
SequenceInputStream: 能對多個inputstream進行順序處理。
輸出流:
基本上每個輸入流類都有一個相應的輸出流類,提供相應的輸出流處理。
同樣,跟數據目的地直接接觸的類有:FileOutputStream和ByteArrayOutputStream,前者實現了把數據流寫入文件 的功能,后者實現了一個輸出流,其中的數據被寫入一個 byte 數組。緩沖區會隨着數據的不斷寫入而自動增長。可使用 toByteArray()
和 toString()
獲取數據。
下面對其它的裝飾類做一下簡單介紹:
BufferedOutputStream: 提供了緩沖功能的輸出流,在寫出完成之前要調用flush來保證數據的輸出。
DataOutputStream: 數據輸出流允許應用程序以適當方式將基本 Java 數據類型寫入輸出流中。然后,應用程序可以使用數據輸入流將數據讀入。
PipedOutputStream: 允許以管道的方式來處理流。可以將管道輸出流連接到管道輸入流來創建通信管道。管道輸出流是管道的發送端。通常,數據由某個線程寫入 PipedOutputStream
對象,並由其他線程從連接的 PipedInputStream
讀取。
PrintStream: 為其他輸出流添加了功能,使它們能夠方便地打印各種數據值表示形式。我們經常用到的System.out或者System.err都是PrintStream。
字符流處理概述:
所有的字符流操作類都繼承自Reader或者Writer這兩個抽象類。
Reader提供的重要方法有:
- read(char[] cbuf);
- read(char[] cbuf, int off, int len);
- read(CharBuffer target);
- read(char[] cbuf);
- read(char[] cbuf, int off, int len);
- read(CharBuffer target);
read(char[] cbuf); read(char[] cbuf, int off, int len); read(CharBuffer target);
他們提供了從流中讀取數據到字符數組或者CharBuffer的功能。
Writer提供的重要方法有:
- write(char[] cbuf);
- write(char[] cbuf, int off, int len);
- write(int c);
- write(String str);
- write(String str, int off, int len);
- write(char[] cbuf);
- write(char[] cbuf, int off, int len);
- write(int c);
- write(String str);
- write(String str, int off, int len);
write(char[] cbuf); write(char[] cbuf, int off, int len); write(int c); write(String str); write(String str, int off, int len);
他們提供了把字符、字符數組或者字符串寫入流中的功能。
字符流處理類概述:
輸入流:
跟數據源直接接觸的類:
CharArrayReader: 從內存中的字符數組中讀入數據,以對數據進行流式讀取。
StringReader:從內存中的字符串讀入數據,以對數據進行流式讀取。
FileReader:從文件中讀入數據。注意這里讀入數據時會根據JVM的默認編碼對數據進行內轉換,而不能指定使用的編碼。所以當文件使用的編 碼不是JVM默認編碼時,不要使用這種方式。要正確地轉碼,使用InputStreamReader。
裝飾類:
BufferedReader:提供緩沖功能,可以讀取行:readLine();
LineNumberReader: 提供讀取行的控制:getLineNumber()等方法。
InputStreamReader: 字節流通向字符流的橋梁:它使用指定的
讀取字節並將其解碼為字符。charset
輸出流:
根數據目的相關的類:
CharArrayWriter:把內存中的字符數組寫入輸出流,輸出流的緩沖區會自動增加大小。輸出流的數據可以通過一些方法重新獲取。
StringWriter: 一個字符流,可以用其回收在字符串緩沖區中的輸出來構造字符串。
FileWriter:把數據寫入文件。
裝飾類:
BufferedWriter:提供緩沖功能。
OutputStreamWriter:字符流通向字節流的橋梁:可使用指定的
將要寫入流中的字符編碼成字節。charset
PrintWriter: 向文本輸出流打印對象的格式化表示形式。
流處理中的其它方法:
mark和reset用於重復讀取某段的數據,如下代碼:
- is = new BufferedInputStream(new FileInputStream("res/input.data"));
- assertTrue(is.available() > 0);
- assertTrue(is.markSupported());
- // The read limit has no effect.
- is.mark(0);
- int first = is.read();
- int second = is.read();
- is.reset();
- int firstAgain = is.read();
- int secondAgain = is.read();
- assertEquals(first, firstAgain);
- assertEquals(second, secondAgain);
- is = new BufferedInputStream(new FileInputStream("res/input.data"));
- assertTrue(is.available() > 0);
- assertTrue(is.markSupported());
- // The read limit has no effect.
- is.mark(0);
- int first = is.read();
- int second = is.read();
- is.reset();
- int firstAgain = is.read();
- int secondAgain = is.read();
- assertEquals(first, firstAgain);
- assertEquals(second, secondAgain);
is = new BufferedInputStream(new FileInputStream("res/input.data")); assertTrue(is.available() > 0); assertTrue(is.markSupported()); // The read limit has no effect. is.mark(0); int first = is.read(); int second = is.read(); is.reset(); int firstAgain = is.read(); int secondAgain = is.read(); assertEquals(first, firstAgain); assertEquals(second, secondAgain);
Writer或者OutputStream中的flush(): 刷新該流的緩沖,用於確保數據的輸出。