6.java I/O 流

Java中的流,可以從不同的角度進行分類。

按照數據流的方向不同可以分爲:輸入流和輸出流。

按照處理數據單位不同可以分爲:字節流和字符流。

按照實現功能不同可以分爲:節點流和處理流。


輸出流:

 

輸入流:

因此輸入和輸出都是從程序的角度來說的。

字節流:一次讀入或讀出是8位二進制。

字符流:一次讀入或讀出是16位二進制。

字節流和字符流的原理是相同的,只不過處理的單位不同而已。後綴是Stream是字節流,而後綴是ReaderWriter是字符流。

 

節點流:直接與數據源相連,讀入或讀出。

直接使用節點流,讀寫不方便,爲了更快的讀寫文件,纔有了處理流。

處理流:與節點流一塊使用,在節點流的基礎上,再套接一層,套接在節點流上的就是處理流。

Jdk提供的流繼承了四大類:InputStream(字節輸入流)OutputStream(字節輸出流),Reader(字符輸入流),Writer(字符輸出流)。


下面是java IO流的結構示意圖:


字符流:

   Reader:用於讀取字符流的抽象類。

       |---BufferedReader:從字符輸入流中讀取文本,緩衝各個字符,從而實現字符、數組和行的高效讀取。 可以指定緩衝區的大小,或者可使用默認的大小。大 多數情況下,默認值就足夠大了。

             |---LineNumberReader:跟蹤行號的緩衝字符輸入流。此類定義了方法setLineNumber(int)和getLineNumbner(),它們可分別用於設置和獲取當前行號。

        |---InputStreamReader:是字節流通向字符流的橋樑:它使用指定的 charset 讀取字節並將其解碼爲字符。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺默認的字符集。

             |---FileReader:用來讀取字符文件的便捷類。此類的構造方法假定默認字符編碼和默認字節緩衝區大小都是適當的。要自己指定這些值,可以先在 FileInputStream 上構造一個 InputStreamReader。

***************************************************************************

   Writer:寫入字符流的抽象類。

        |---BufferedWriter:將文本寫入字符輸出流,緩衝各個字符,從而提供單個字符、數組和字符串的高效寫入。

        |---OutputStreamWriter:是字符流通向字節流的橋樑:可使用指定的 charset 將要寫入流中的字符編碼成字節。它使用的字符集可以由名稱指定或顯式給定,否則將接受平臺默認的字符集。

             |---FileWriter:用來寫入字符文件的便捷類。此類的構造方法假定默認字符編碼和默認字節緩衝區大小都是可接受的。要自己指定這些值,可以先在 FileOutputStream 上構造一個 OutputStreamWriter。

****************************************************************************

   字節流:

   InputStream:是表示字節輸入流的所有類的超類。

        |--- FileInputStream:從文件系統中的某個文件中獲得輸入字節。哪些文件可用取決於主機環境。FileInputStream 用於讀取諸如圖像數據之類的原始字節流。要讀取字符流,請考慮使用 FileReader。

        |--- FilterInputStream:包含其他一些輸入流,它將這些流用作其基本數據源,它可以直接傳輸數據或提供一些額外的功能。

             |--- BufferedInputStream:該類實現緩衝的輸入流。

**************************************************************************

   OutputStream:此抽象類是表示輸出字節流的所有類的超類。

        |--- FileOutputStream:文件輸出流是用於將數據寫入 File 或 FileDescriptor 的輸出流。

        |--- FilterOutputStream:此類是過濾輸出流的所有類的超類。

              |--- BufferedOutputStream:該類實現緩衝的輸出流。


   流的操作規律:

   1、明確源和目的。

   數據源:就是需要讀取,可以使用兩個體系:InputStream、Reader;

   數據匯:就是需要寫入,可以使用兩個體系:OutputStream、Writer;

   2、操作的數據是否是純文本數據?

   如果是:數據源:Reader

           數據匯:Writer 

   如果不是:數據源:InputStream

             數據匯:OutputStream

   3、雖然確定了一個體系,但是該體系中有太多的對象,到底用哪個呢?

   明確操作的數據設備。

   數據源對應的設備:硬盤(File),內存(數組),鍵盤(System.in)

   數據匯對應的設備:硬盤(File),內存(數組),控制檯(System.out)。

   4、需要在基本操作上附加其他功能嗎?比如緩衝。

   如果需要就進行裝飾。

/記住,只要一讀取鍵盤錄入,就用這句話。

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));



下面是一個應用的例子:
[java] view plain copy
  1. <span style="color:#000000;">import java.io.*;  
  2. import java.nio.CharBuffer;  
  3. import java.util.Scanner;  
  4.   
  5. import org.junit.Test;  
  6.   
  7. public class Test1 {  
  8.     @Test  
  9.     public void testFile() throws IOException {  
  10.   
  11.         File file1 = new File("D:/test");  
  12.         file1.mkdir(); // 在D盤下創建test目錄  
  13.         File[] fileArr = file1.listFiles(); // 獲取目錄下的所有文件  
  14.         for (File f : fileArr) { // 輸出目錄下的文件名  
  15.             System.out.println(f.getName());  
  16.         }  
  17.           
  18.         String str;  
  19.         System.out.println("請輸入需要複製的文件名:");  
  20.         BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));  
  21.             str = buf.readLine();  
  22.         if(str.equals("1.txt")){  
  23.             new copyFile().copyTxt();  
  24.         }  
  25.         if(str.equals("1.jpg")){  
  26.             new copyFile().copyJpg();  
  27.         }  
  28.           
  29.         buf.close();  
  30.         File[] fileArr2 = file1.listFiles(); // 獲取目錄下的所有文件  
  31.         for (File f : fileArr2) { // 輸出目錄下的文件名  
  32.             System.out.println(f.getName());  
  33.         }  
  34.           
  35.   
  36.     }  
  37.   
  38. }  
  39.   
  40. class copyFile {  
  41.     public void copyTxt() throws IOException {  
  42.         int number = 0;  
  43.         File file1 = new File("D:/test/1.txt");  
  44.         File file2 = new File("D:/test/2.txt");  
  45.         BufferedReader bfRead;  
  46.         BufferedWriter bfWrite;  
  47.         bfWrite = new BufferedWriter(new FileWriter(file2));  
  48.         char[] arry = new char[1024];  
  49.         FileReader fRead = new FileReader(file1);  
  50.         bfRead = new BufferedReader(fRead);  
  51.   
  52.         while ((number = bfRead.read(arry)) != -1) {  
  53.             bfWrite.write(arry, 0, number);  
  54.         }  
  55.   
  56.         bfWrite.close();  
  57.         bfRead.close();  
  58.   
  59.     }  
  60.   
  61.     public void copyJpg() throws IOException  {  
  62.               
  63.         File file1=  new File("D:/test/1.jpg");  
  64.         File file2= new File("D:/test/2.jpg");  
  65.         FileInputStream bfRead=new FileInputStream(file1);;  
  66.         FileOutputStream bfWrite=new FileOutputStream(file2);  
  67.         try {  
  68.             byte[] arry = new byte[1024]; // 定義數組,傳遞流之間的數據  
  69.             int count = 0;  
  70.   
  71.             while((count = bfRead.read(arry)) != -1) {  
  72.                 bfWrite.write(arry, 0, count);  
  73.             }  
  74.   
  75.               
  76.         } catch (FileNotFoundException e) {  
  77.             System.out.println("filenotfound");  
  78.         } catch (IOException e) {  
  79.             System.out.println("IoException");  
  80.         }  
  81.         bfWrite.close();  
  82.         bfRead.close();  
  83.   
  84.     }  
  85. }  
  86. </span>  

對文件進行操作:FileInputStream(字節輸入流),FileOutputStream(字節輸出流),FileReader(字符輸入流),FileWriter(字符輸出流)

對管道進行操作:PipedInputStream(字節輸入流),PipedOutStream(字節輸出流),PipedReader(字符輸入流),PipedWriter(字符輸出流)

PipedInputStream的一個實例要和PipedOutputStream的一個實例共同使用,共同完成管道的讀取寫入操作。主要用於線程操作。

字節/字符數組:ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter是在內存中開闢了一個字節或字符數組。

Buffered緩衝流::BufferedInputStreamBufferedOutputStreamBufferedReader,BufferedWriter,是帶緩衝區的處理流,緩衝區的作用的主要目的是:避免每次和硬盤打交道,提高數據訪問的效率。

轉化流:InputStreamReader/OutputStreamWriter,把字節轉化成字符。

數據流:DataInputStreamDataOutputStream

因爲平時若是我們輸出一個8個字節的long類型或4個字節的float類型,那怎麼辦呢?可以一個字節一個字節輸出,也可以把轉換成字符串輸出,但是這樣轉換費時間,若是直接輸出該多好啊,因此這個數據流就解決了我們輸出數據類型的困難。數據流可以直接輸出float類型或long類型,提高了數據讀寫的效率。

打印流:printStreamprintWriter,一般是打印到控制檯,可以進行控制打印的地方。

對象流:ObjectInputStreamObjectOutputStream,把封裝的對象直接輸出,而不是一個個在轉換成字符串再輸出。

序列化流:SequenceInputStream

對象序列化:把對象直接轉換成二進制,寫入介質中。

使用對象流需要實現Serializable接口,否則會報錯。而若用transient關鍵字修飾成員變量,不寫入該成員變量,若是引用類型的成員變量爲null,值類型的成員變量爲0.


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