1. 流的分類
按數據流的方向不同:輸入流,輸出流。
按處理數據單位不同:字節流,字符流。
(1) 字節流:數據流中最小的數據單元是字節。
(2)字符流:數據流中最小的數據單元是字符, Java中的字符是Unicode編碼,一個字符占用兩個字節。
按功能不同:節點流,處理流。
(1)程序用於直接操作目標設備所對應的類叫節點流。
(2)程序通過一個間接流類去調用節點流類,以達到更加靈活方便地讀寫各種類型的數據,這個間接流類就是處理流。
2. 節點流
2.1 節點流的類型
(1)File 文件流。對文件進行讀、寫操作 :FileReader、FileWriter、FileInputStream、FileOutputStream。、
(2)Memory
1)從/向內存數組讀寫數據: CharArrayReader與 CharArrayWriter、ByteArrayInputStream與ByteArrayOutputStream。
2)從/向內存字符串讀寫數據 StringReader、StringWriter、StringBufferInputStream。
(3)Pipe管道流。 實現管道的輸入和輸出(進程間通信): PipedReader與PipedWriter、PipedInputStream與PipedOutputStream。
2.2 節點流執行的圖示
3. 處理流
3.1 處理流的類型
- (1)Buffering緩沖流:在讀入或寫出時,對數據進行緩存,以減少I/O的次數:BufferedReader與BufferedWriter、BufferedInputStream與BufferedOutputStream。
- (2)Filtering 濾流:在數據進行讀或寫時進行過濾:FilterReader與FilterWriter、FilterInputStream與FilterOutputStream。
- (3)Converting between Bytes and Characters 轉換流:按照一定的編碼/解碼標准將字節流轉換為字符流,或進行反向轉換(Stream到Reader):InputStreamReader、OutputStreamWriter。
- (4)Object Serialization 對象流 :ObjectInputStream、ObjectOutputStream。
- (5)DataConversion數據流: 按基本數據類型讀、寫(處理的數據是Java的基本類型(如布爾型,字節,整數和浮點數)):DataInputStream、DataOutputStream 。
- (6)Counting計數流: 在讀入數據時對行記數 :LineNumberReader、LineNumberInputStream。
- (7)Peeking Ahead預讀流: 通過緩存機制,進行預讀 :PushbackReader、PushbackInputStream。
- (8)Printing打印流: 包含方便的打印方法 :PrintWriter、PrintStream。
3.2 處理流執行的圖示
3.3 緩沖流
【1】對I/O進行緩沖是一種常見的性能優化,緩沖流為I/O流增加了內存緩沖區,增加緩沖區的兩個目的:
(1)允許Java的I/O一次不只操作一個字符,這樣提高䇖整個系統的性能;
(2)由於有緩沖區,使得在流上執行skip、mark和reset方法都成為可能。
【2】緩沖流:它是要“套接”在相應的節點流之上,對讀寫的數據提供了緩沖的功能,
提高了讀寫的效率,同時增加了一些新的方法。例如:BufferedReader中的readLine方法,
BufferedWriter中的newLine方法。
【3】J2SDK提供了4種緩存流,常用的構造方法為:
//字符輸入流 BufferedReader(Reader in)//創建一個32字節的緩沖區 BufferedReader(Reader in, int size)//size為自定義緩存區的大小 //字符輸出流 BufferedWriter(Writer out) BufferedWriter(Writer out, int size) //字節輸入流 BufferedInputStream(InputStream in) BufferedInputStream(InputStream in, int size) //字節輸出流 BufferedOutputStream(OutputStream in) BufferedOutputStream(OutputStream in, int size)
【4】其他
(1)緩沖輸入流BufferedInputSTream除了支持read和skip方法意外,還支持其父類的mark和reset方法;
(2)BufferedReader提供了一種新的ReadLine方法用於讀取一行字符串(以\r或\n分隔);
(3)BufferedWriter提供了一種新的newLine方法用於寫入一個行分隔符;
(4)對於輸出的緩沖流,BufferedWriter和BufferedOutputStream,寫出的數據會先在內存中緩存,
使用flush方法將會使內存的數據立刻寫出。
示例1:
import java.io.*; public class TestBufferStream1 { public static void main(String[] args) { try { FileInputStream fis = new FileInputStream( "d:\\JavaProject\\demo13\\ProcessingStream\\TestBufferStream1.java"); BufferedInputStream bis = new BufferedInputStream(fis); int c = 0; System.out.println((char)bis.read()); System.out.println((char)bis.read()); bis.mark(100);/*在當前輸入流的當前位置上做一個標志,允許最多再讀入100個字節*/ for(int i=0;i<=10 && (c=bis.read())!=-1;i++){ System.out.print((char)c+" "); } System.out.println(); bis.reset();/*把輸入指針返回到以前所做的標志處*/ for(int i=0;i<=10 && (c=bis.read())!=-1;i++){ System.out.print((char)c+" "); } bis.close(); } catch (IOException e) {e.printStackTrace();} } }
示例2:
import java.io.*; public class TestBufferStream2 { public static void main(String[] args) { try{ BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\JavaProject\\demo13\\BufferStream\\dat2.txt")); BufferedReader br = new BufferedReader(new FileReader("D:\\JavaProject\\demo13\\BufferStream\\dat2.txt")); String s = null; for(int i=0;i<10;i++) { s = String.valueOf(Math.random());//產生一個小於1的正的隨機數,並轉換成字符串形式 bw.write(s);//把字符串s寫入到dat2.txt文件中 bw.newLine();//寫入一個行分隔符 } bw.flush();//使用flush方法將會使內存的數據立刻寫出 while((s=br.readLine()) != null) { System.out.println(s); } bw.close(); br.close(); } catch(IOException e) { e.printStackTrace(); } } }
3.4 轉換流
轉換流有兩種:
(1)InputStreamReader:將字節流轉換為字符流;
(2)OutputStreamWriter:將字符流轉換為字節流。
什么時候使用轉換流?由以下分析: 流對象很多,就要明確使用哪個流對象。
通過三點來完成: 1、明確數據的來源和數據到達的目的地。 來源:輸入流 [InputStream,Reader]。 目的:輸出流 [OutputStream,Writer]。 2、操作的數據是否是純文本。 是:字符流,使用Reader與Writer; 否:字節流,使用InputStream與OutputStream。 3、明確要使用哪個具體的對象。 通過設備來進行區分: 源設備:內存用數組,硬盤就加file,鍵盤用System.in; 目的設備:內存用數組,硬盤就加file,鍵盤用System.out。 4、明確是否還需要其他額外功能:例如 (1)是否需要較高的效率,即是否需要使用緩沖區,是就加上Buffered; (2)是否需要轉換,是,就使用轉換流,InputStreamReader 和 OutputStreamWriter。
用一個例子簡單的說明: 將鍵盤錄入的數據保存到一個文件中,輸入“over”時表示錄入結束。 詳細分析:
源:從InputStream,Reader中選擇; 因為是鍵盤錄入的是純文本,所以使用Reader。 設備:鍵盤,所以用System.in; 發現System.in是字節流的操作,與Reader(字符流)矛盾, 這時就要用到轉換流 InputStreamReader 。為了提高操作效率,使用緩沖技術,選擇BufferedReader。 目的:從 OutputStream,Writer中選擇。 因為是文本文件,所以選擇Writer。 設備:硬盤上,一個文件,選擇FileWriter。 為了提高操作效率,使用緩沖技術,選擇BufferedWriter。
示例1:
import java.io.*; class ReadinFile { public static void main(String[] args)throws IOException //這里為了方便閱讀,先不做異常處理。 { BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bufw=new BufferedWriter(new FileWriter("readin.txt")); String line=null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; bufw.write(line); bufw.newLine(); } bufw.close(); bufr.close(); } }
示例2:
import java.io.*; public class TestTransForm { public static void main(String[] args) throws IOException //這里為了方便閱讀,先不做異常處理。 { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); OutputStreamWriter osw = new OutputStreamWriter( new FileOutputStream("D:\\JavaProject\\demo13\\TransStream\\TransForm.txt",true)); BufferedWriter bw = new BufferedWriter(osw); String str = null; str = br.readLine(); while(str != null) { if(str.equalsIgnoreCase("exit")) break; bw.write(str); bw.newLine(); str = br.readLine(); } br.close(); bw.close(); } }
注意:
(1)構造方法:public FileOutputStream(String name,boolean append) throws FileNotFoundException
如果append為True,輸出字節流就寫入文件的末尾,而不是開頭(覆蓋原來的內容);
如果append為False,輸出字節流就寫入文件的開頭,即覆蓋原來的內容從文件開始處寫內容。
(2)構造方法:public FileOutputStream(String name) throws FileNotFoundException
每次覆蓋原文件的內容,從文件開始處寫內容。
3.5 數據流——數據的存儲和數據恢復
數據流:DataInputStream和DataOutputStream
(0)DataInputStream和DataOutputStream是面向字節的,因此要使用InputStream和OutputStream。
(1)DataInputStream和DataOutputStream分別繼承InputStream和OutputStream,
它們屬於處理流,需要分別“套接”在InputStream和OutputStream類型的節點流上。
(2)DataInputStream和DataOutputStream提供了可以存取與機器無關的Java原始類數據(如:int,double等)的方法。
(3)DataInputStream和DataOutputStream的構造方法:
DataInputStream(InputStream in) DataOutputStream(OutputStream out)
示例1:
import java.io.*; public class TestDataStream { public static void main(String[] args) throws IOException { FileOutputStream fout = new FileOutputStream("D:/JavaProject/demo13_IO/DataStream/demo.txt",true); BufferedOutputStream bout = new BufferedOutputStream(fout); DataOutputStream dout = new DataOutputStream(bout); /*DataOutputStream,BufferedOutputStream,FileOutputStream這里使用了流棧。*/ dout.writeInt(110); dout.writeUTF("hello,中國"); dout.writeFloat(3.14f); dout.writeChar(97);/*97對應的是'a'*/ dout.close();/*如果正在使用一個流棧,程序關閉最上面的一個流也就自動的關閉了棧中的所有底層流。*/ FileInputStream fin = new FileInputStream("D:/JavaProject/demo13_IO/DataStream/demo.txt"); BufferedInputStream bin = new BufferedInputStream(fin); DataInputStream din = new DataInputStream(bin); int i = din.readInt(); String str = din.readUTF(); float f = din.readFloat(); char c = din.readChar(); fin.close();/*如果正在使用一個流棧,程序關閉最上面的一個流也就自動的關閉了棧中的所有底層流。*/ System.out.println("int:"+i+"\nString:"+str+"\nfloat:"+f+"\nchar:"+c); } }
編譯,運行:
D:\JavaProject\demo13_IO\DataStream>javac TestDataStream.java D:\JavaProject\demo13_IO\DataStream>java TestDataStream int:110 String:hello,中國 float:3.14 char:a
注意:
int i = din.readInt();
String str = din.readUTF();
float f = din.readFloat();
char c = din.readChar();
/*此段代碼的順序不能亂,要保證先寫入的先讀出來的原則,否則會出現錯誤。
* 因此,我們在寫代碼的時候,我們必須:
* 要么為文件中的數據采用固定的格式;
* 要么將額外的信息保存到文件中,以便能夠對其進行解析以確定數據的尋訪位置。
*/
---------------------
作者:Joohong
來源:CSDN
原文:https://blog.csdn.net/jingzi123456789/article/details/72123937
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!