JAVA 中的IO流

JAVA 中的IO流
一、流的概念
       流(stream)的概念源於UNIX中管道(pipe)的概念。在UNIX中,管道是一條不間斷的字節流,用來實現程序或進程間的通信,或讀寫外圍設備、外部文件等。
       一個流,必有源端和目的端,它們可以是計算機內存的某些區域,也可以是磁盤文件,甚至可以是Internet上的某個URL。
        流的方向是重要的,根據流的方向,流可分爲兩類:輸入流和輸出流。用戶可以從輸入流中讀取信息,但不能寫它。相反,對輸出流,只能往輸入流寫,而不能讀它。
       實際上,流的源端和目的端可簡單地看成是字節的生產者和消費者,對輸入流,可不必關心它的源端是什麼,只要簡單地從流中讀數據,而對輸出流,也可不知道它的目的端,只是簡單地往流中寫數據。 
       形象的比喻——水流 ,文件======程序 ,文件和程序之間連接一個管道,水流就在之間形成了,自然也就出現了方向:可以流進,也可以流出.便於理解,這麼定義流: 流就是一個管道里面有流水,這個管道連接了文件和程序。
 
"IO"對程序語言的設計者來說是一項難度極高的任務.編程思想中這樣說過,可見要把IO徹底搞清楚並非簡單之事.我也苦心研究過IO但是還不能完全理解.只是理解了主要的一些功能.File類的名字極具的富有欺騙性,剛看或許會認爲是一個關於文件的類,但它不是.可以用它來表示某個文件的名字,也可以用它來表示目錄裏的一組文件的名字.如果它表示的是一組文件,那麼你還可以用list()方法來進行查詢,它返回String數組.File類的功能不僅限於顯示文件或者目錄.還可以幫你創建心的目錄甚至是目錄路徑.此外還可以用來檢查文件的屬性,判斷文件是否存在,刪除文件等等N多功能.個人覺的IO流是J2SE的核心技術之一,雖然J2EE的程序員精通於它,但是掌握基本的流操作和原理也是很有必要的.說了半天什麼是"流"呢?所謂"流"就是一種能生成或接受數據的,代表數據的源和目標的對象,流把I/O設備內部的具體操作封裝了起來.JDK文檔上說到JAVA的I/O類庫分成輸入和輸出兩大部分也就是通常說的讀和寫.所有的InputStream和Reader的派生類都有一個基本的繼承來的能讀取單個或者byte數組的read()方法.反之所有的OutputStream和Writer的派生類都有一個基本的能寫入單個或byte數組的write()方法.
InputStream的任務就是代表那些從各種輸入源獲取數據的類,這些源主要有byte數組,String對象,文件,管道,流序列,Internet.這些數據源各自都有與之相對應的InputStream的子類.
1)ByteArrayInputStream:以緩衝區內存爲InputStream
2)StringBufferInputStream:以String爲InputStream
3)FileInputStream:專門用來讀文件
4)PipedInputStream:從PipedOutputStream提取數據實現"管道"功能
5)SequenceInputStream:把兩個或者多個InputStream合併成一個.
6)FilterInputStream:一個爲decorator定義接口用的抽象類.
OutputStream是解決往哪裏輸出的類,是byte數組,文件或者是管道.
1)ByteArrayOutputStream:在內存裏創建一個緩衝區,數據送到流裏就是寫入這個緩衝區.
2)FileOutputStream:把數據寫入文件.
3)PipedOutputStream:寫入這個流的數據,最終都會變成與之相關聯的PipedInputStream的數據源.
4)FilterOutputStream:一個能decorator提供接口的抽象類.
自從java1.1對最底層的I/O流類庫作了重大修改之後,我們看到了Reader和Writer,這個時候我們也許會想reader和writer是不是要取代InputStream和OutputStream呢?不過事實並非如此,雖然InputStream和OutputStream的部分功能已經被淘汰(你繼續用編譯會有異常),但是仍然有很多東西是有價值的,它們是面向byte的I/O流,也就是字節流.而Reader和Writer則提供的是Unicode的兼容,也就是字符類.Reader和Writer(我稱爲讀流和寫流)我覺的主要的用途在與國際化問題.而原來的I/O類庫只支持8位的字節,也就是輸入輸出流,因爲不能很好的處理16位的unicode字符.這裏說一個概念就是"標準I/O"是Unix的概念,它的意思是一個程序使用一個信息流.所有輸入都是從"標準輸入"流進來的,輸出都是從"標準輸出"出去的.錯誤的消息有"標準錯誤"標準I/O的優點是可以很容易的和程序串連起來,並且把一個程序的輸出當作另一個程序的輸入.新IO是JAVA1.4引入的一個新的I/O類庫,位於"java.nio.*"包,這麼做只有一個目的就是速度.不過至於這個包中的類我還沒具體的使用過HOHO.
JAVA的"對象系列化"能讓一個實現了Serializable接口的對象轉換成一組byte,這樣日後要用這個對象的時候,就可以從byte數據恢復出來,簡單的說就是把對象保存在外部文件中.而且這種方法也是跨平臺的,你無需考慮自己的對象文件應用於什麼平臺,這些技術細節虛擬機爲我們實現了.序列化一個對象還是比較簡單的,只要讓它實現Serializable接口就行了(這是一個標記接口(tagging interface)沒有方法的接口).但是,當語言引入序列化概念之後,它的很多標準類庫的類,包括primitive的wrapper類,所有的容器類,以及別的很多類,都會相應地發生改變.甚至連Class對象都會被序列化.要想序列化對象,你必須先創建一個OutputStream,然後把它嵌進ObjectOutputStream.這時,你就能用writeObject( )方法把對象寫入OutputStream了.讀的時候,你得把InputStream嵌到ObjectInputStream裏面,然後再調用readObject( )方法.不過這樣讀出來的,只是一個Object的對象.對象序列化的重要用途就是Bean技術和RMI(遠程方法調用).
如果想深刻學習掌握JAVA的I/O流,我在這裏推薦Elliotte Rusty Harold寫的<<Java I/O>>(O’Reilly, 1999)這本書.
二、流的分類
  1. java.io包中的類對應兩類流,一類流直接從指定的位置(如磁盤文件或內存區域)讀或寫,這類流稱爲結點流(node stream),其它的流則稱爲過濾器(filters)。過濾器輸入流往往是以其它輸入流作爲它的輸入源,經過過濾或處理後再以新的輸入流的形式提供給用戶,過濾器輸出流的原理也類似。
  2. Java的常用輸入、輸出流
java.io包中的stream類根據它們操作對象的類型是字符還是字節可分爲兩大類: 字符流和字節流。
 
  • Java的字節流
InputStream是所有字節輸入流的祖先,而OutputStream是所有字節輸出流的祖先。
  • Java的字符流
Reader是所有讀取字符串輸入流的祖先,而writer是所有輸出字符串的祖先。
結合開始所說的輸入/輸出流 ,出現了個一小框架。

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

JAVA字節流

  • FileInputStream和FileOutputStream
    這兩個類屬於結點流,第一個類的源端和第二個類的目的端都是磁盤文件,它們的構造方法允許通過文件的路徑名來構造相應的流。如:
    FileInputStream infile = new FileInputStream("myfile.dat");
    FileOutputStream outfile = new FileOutputStream("results.dat");

要注意的是,構造FileInputStream, 對應的文件必須存在並且是可讀的,而構造FileOutputStream時,如輸出文件已存在,則必須是可覆蓋的。

  • BufferedInputStream和BufferedOutputStream
    它們是過濾器流,其作用是提高輸入輸出的效率。
  • DataInputStream和DataOutputStream
    這兩個類創建的對象分別被稱爲數據輸入流和數據輸出流。這是很有用的兩個流,它們允許程序按與機器無關的風格讀寫Java數據。所以比較適合於網絡上的數據傳輸。這兩個流也是過濾器流,常以其它流如InputStream或OutputStream作爲它們的輸入或輸出。
    Java的字符流

        字符流主要是用來處理字符的。Java採用16位的Unicode來表示字符串和字符,對應的字符流按輸入和輸出分別稱爲readers和writers。
    • InputStreamReader和OutputStreamWriter
      在構造這兩個類對應的流時,它們會自動進行轉換,將平臺缺省的編碼集編碼的字節轉換爲Unicode字符。對英語環境,其缺省的編碼集一般爲ISO8859-1。
    • BufferedReader和BufferedWriter
      這兩個類對應的流使用了緩衝,能大大提高輸入輸出的效率。這兩個也是過濾器流,常用來對InputStreamReader和OutputStreamWriter進行處理。如:
      import java.io.*;
      public class Echo {
        public static void main(String[] args) {
          BufferedReader in =
            new BufferedReader(
              new InputStreamReader(System.in));
          String s;
          try {
            while((s = in.readLine()).length() != 0)
              System.out.println(s);
            // An empty line terminates the program
          } catch(IOException e) {
            e.printStackTrace();
          }
        }
      }
    該程序接受鍵盤輸入並回顯。
    對BufferedReader類,該類的readLine()方法能一次從流中讀入一行,但對於BufferedWriter類,就沒有一次寫一行的方法,所以若要向流中一次寫一行,可用PrintWriter類將原來的流改造成新的打印流,PrintWriter類有一個方法println(),能一次輸出一行。如:
    ............
    PrintWriter out = new PrintWriter(new BufferedWriter(
          new FileWriter("D:/javacode/test.txt")));
    out.println("Hello World!");
    out.close();
    ............

    例子:

    1,與控制檯相關。的讀入/寫出。 實現了字符串的複製。

    import java.io.*;
    public class TextRead{

    public static void main(String[] args){
       BufferedReader bf = null;/*BufferedReader相當於一個大桶,其實就是內存,這裏實現了大量大量的讀寫 ,而不是讀一個字節或字符就直接寫如硬盤,加強了對硬盤的保護。*/
       try{
        while(true){ // while(true){}循環保證程序不會結束
        
           bf = new BufferedReader(new InputStreamReader(System.in));
           /*System.in 爲標準輸入,System.out爲標準輸出*/
           /*InputStreamReader用語將字節流到字符流的轉化,這也就是處理流了
            *在這裏相當與2個管道接在System.in與程序之間。
            *readLine()方法功能比較好用,也就通過處理流來實現更好功能。
            **/
         String line = bf.readLine();
         System.out.println(line);
        }  
       }catch(Exception e){
        e.printStackTrace();
       }finally{
        //一定要關閉流,用完後。最好放在

    filally 裏面。  
        try{   
         if(bf!=null){
          bf.close();
         }
        }catch(Exception e){
           e.printStackTrace();
        }
        
       }
       
    }

    }

    2,與文件 相關的 讀寫。    實現了文件的複製。
    import java.io.*;
    public class TextRead{

    public static void main(String[] args){
       File fin,fout;  
       BufferedReader bf = null;
       PrintWriter pw = null;
       try{
        fin = new File("zzc.txt"); //注意文件與程序都要在同一個文件夾下。zzc.txt爲要被複制的文件。
       
        fout = new File("copyzzc.txt"); //如果沒有會自動創建。
       
        bf = new BufferedReader(new FileReader(fin));
       
          pw = new PrintWriter(fout); //PrintWriter爲打印流,也可以使用BufferedWriter.
        String line = bf.readLine();
        while(line!=null){
         pw.println(line);
        
         line = bf.readLine();
        }
       
       
       }catch(Exception e){
        e.printStackTrace();
       
       }finally{
        try{
        //關閉 文件。
         if(bf!=null){
          bf.close();
          bf = null;
         }
         if(pw!=null){
          pw.close();
          pw = null;
         }
        }catch(Exception e){
         e.printStackTrace();
        }
       }
       
    }

    }

    也是在一個百度好友上看到一篇關於流的文章寫的更詳細,把好多過時的不用的,哪寫常用的都分類了,

    還有好多類:

    像RandomAccessFile類,序列化接口,都十分重要。

    Java有一種特殊類型的IO數據流——DataOutputStream——它可以保證“無論數據來自何種機器,只要使用一個DataInputStream收取這些數據,就可用本機正確的格式保存它們.

    以後在把示例加上,還有寫比較好的方法。

    其實感覺這已經是固定模式了,一提到從鍵盤讀取數據 就會聯想到:

    new BufferedReader(new InputStreamReader(System.in))

    現在水平達不到,還是記些固定格式比較好,以至於會用。

    某個老師也說過,創新是建立在紮實的基礎之上,越來越覺得基礎重要了。

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