JAVA輸入輸出流

OneCode2World發表於2015-08-04

         Java輸入輸出流

分類: Java 52309人閱讀 評論(15) 收藏 舉報

目錄(?)[+]


1.什麼是IO

      Java中I/O操作主要是指使用Java進行輸入,輸出操作. Java所有的I/O機制都是基於資料流進行輸入輸出,這些資料流表示了字元或者位元組資料的流動序列Java的I/O流提供了讀寫資料的標準方法。任何Java中表示資料來源的物件都會提供以資料流的方式讀寫它的資料的方法。  

      Java.io是大多數面向資料流的輸入/輸出類的主要軟體包。此外,Java也對塊傳輸提供支援,在核心庫 java.nio中採用的便是塊IO。

  流IO的好處是簡單易用,缺點是效率較低。塊IO效率很高,但程式設計比較複雜。 
      Java IO模型  :
      Java的IO模型設計非常優秀,它使用Decorator模式,按功能劃分Stream,您可以動態裝配這些Stream,以便獲得您需要的功能。例如,您需要一個具有緩衝的檔案輸入流,則應當組合使用FileInputStream和BufferedInputStream。 

2.資料流的基本概念

        資料流是一串連續不斷的資料的集合,就象水管裡的水流,在水管的一端一點一點地供水,而在水管的另一端看到的是一股連續不斷的水流。資料寫入程式可以是一段、一段地向資料流管道中寫入資料,這些資料段會按先後順序形成一個長的資料流。對資料讀取程式來說,看不到資料流在寫入時的分段情況,每次可以讀取其中的任意長度的資料,但只能先讀取前面的資料後,再讀取後面的資料。不管寫入時是將資料分多次寫入,還是作為一個整體一次寫入,讀取時的效果都是完全一樣的。 

      “流是磁碟或其它外圍裝置中儲存的資料的源點或終點。”

    在電腦上的資料有三種儲存方式,一種是外存,一種是記憶體,一種是快取。比如電腦上的硬碟,磁碟,U盤等都是外存,在電腦上有記憶體條,快取是在CPU裡面的。外存的儲存量最大,其次是記憶體,最後是快取,但是外存的資料的讀取最慢,其次是記憶體,快取最快。這裡總結從外存讀取資料到記憶體以及將資料從記憶體寫到外存中。對於記憶體和外存的理解,我們可以簡單的理解為容器,即外存是一個容器,記憶體又是另外一個容器。那又怎樣把放在外存這個容器內的資料讀取到記憶體這個容器以及怎麼把記憶體這個容器裡的資料存到外存中呢?

     在Java類庫中,IO部分的內容是很龐大的,因為它涉及的領域很廣泛:

         標準輸入輸出,檔案的操作,網路上的資料流,字串流,物件流,zip檔案流等等,java中將輸入輸出抽象稱為流,就好像水管,將兩個容器連線起來。將資料衝外存中讀取到記憶體中的稱為輸入流,將資料從記憶體寫入外存中的稱為輸出流。

    流是一個很形象的概念,當程式需要讀取資料的時候,就會開啟一個通向資料來源的流,這個資料來源可以是檔案,記憶體,或是網路連線。類似的,當程式需要寫入資料的時候,就會開啟一個通向目的地的流。

      總結的基本概念如下:

1) 資料流

    一組有序,有起點和終點的位元組的資料序列。包括輸入流和輸出流。

  

2) 輸入流(Input  Stream):

      程式從輸入流讀取資料來源。資料來源包括外界(鍵盤、檔案、網路…),即是將資料來源讀入到程式的通訊通道

     

 3) 輸出流

    程式向輸出流寫入資料。將程式中的資料輸出到外界(顯示器、印表機、檔案、網路…)的通訊通道。

         

採用資料流的目的就是使得輸出輸入獨立於裝置。

Input  Stream不關心資料來源來自何種裝置(鍵盤,檔案,網路)
Output  Stream不關心資料的目的是何種裝置(鍵盤,檔案,網路)

4 資料流分類:

流序列中的資料既可以是未經加工的原始二進位制資料,也可以是經一定編碼處理後符合某種格式規定的特定資料。因此Java中的流分為兩種:
 1)  位元組流:資料流中最小的資料單元是位元組
 2)  字元流:資料流中最小的資料單元是字元, Java中的字元是Unicode編碼,一個字元佔用兩個位元組。

3. 標準I/O

      Java程式可通過命令列引數與外界進行簡短的資訊交換,同時,也規定了與標準輸入、輸出裝置,如鍵盤、顯示器進行資訊交換的方式。而通過檔案可以與外界進行任意資料形式的資訊交換。

1. 命令列引數

  1. public class TestArgs {  
  2.     public static void main(String[] args) {  
  3.         for (int i = 0; i < args.length; i++) {  
  4.             System.out.println("args[" + i + "] is <" + args[i] + ">");  
  5.         }  
  6.     }  
  7. }  

執行命令:java Java C VB

執行結果:

args[0] is <Java>

args[1] is <C>

args[2] is <VB>

2. 標準輸入,輸出資料流

java系統自帶的標準資料流:java.lang.System:

  1. java.lang.System   
  2. public final class System  extends Object{   
  3.    static  PrintStream  err;//標準錯誤流(輸出)  
  4.    static  InputStream  in;//標準輸入(鍵盤輸入流)  
  5.    static  PrintStream  out;//標準輸出流(顯示器輸出流)  
  6. }  

注意:
(1)System類不能建立物件,只能直接使用它的三個靜態成員。
(2)每當main方法被執行時,就自動生成上述三個物件。

1) 標準輸出流 System.out

   System.out向標準輸出裝置輸出資料,其資料型別為PrintStream。方法:

      Void print(引數)
      Void println(引數)

2)標準輸入流 System.in

    System.in讀取標準輸入裝置資料(從標準輸入獲取資料,一般是鍵盤),其數 據型別為InputStream。方法:

        int read()  //返回ASCII碼。若,返回值=-1,說明沒有讀取到任何位元組讀取工作結束。
         int read(byte[] b)//讀入多個位元組到緩衝區b中返回值是讀入的位元組數
例如:
  1. import java.io.*;  
  2. public class StandardInputOutput {  
  3.     public static void main(String args[]) {  
  4.         int b;  
  5.         try {  
  6.             System.out.println("please Input:");  
  7.             while ((b = System.in.read()) != -1) {  
  8.                 System.out.print((char) b);  
  9.             }  
  10.         } catch (IOException e) {  
  11.             System.out.println(e.toString());  
  12.         }  
  13.     }  
  14. }  
等待鍵盤輸入,鍵盤輸入什麼,就列印出什麼:

3)標準錯誤流

   System.err輸出標準錯誤,其資料型別為PrintStream。可查閱API獲得詳細說明。

    標準輸出通過System.out呼叫println方法輸出引數並換行,而print方法輸出引數但不換行。println或print方法都通 過過載實現了輸出基本資料型別的多個方法,包括輸出引數型別為boolean、char、int、long、float和double。同時,也過載實現 了輸出引數型別為char[]、String和Object的方法。其中,print(Object)和println(Object)方法在執行時將調 用引數Object的toString方法。

  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStreamReader;  
  4.   
  5. public class StandardInputOutput {  
  6.     public static void main(String args[]) {  
  7.         String s;  
  8.         // 建立緩衝區閱讀器從鍵盤逐行讀入資料  
  9.         InputStreamReader ir = new InputStreamReader(System.in);  
  10.         BufferedReader in = new BufferedReader(ir);  
  11.         System.out.println("Unix系統: ctrl-d 或 ctrl-c 退出"  
  12.                 + "\nWindows系統: ctrl-z 退出");  
  13.         try {  
  14.             // 讀一行資料,並標準輸出至顯示器  
  15.             s = in.readLine();  
  16.             // readLine()方法執行時若發生I/O錯誤,將丟擲IOException異常  
  17.             while (s != null) {  
  18.                 System.out.println("Read: " + s);  
  19.                 s = in.readLine();  
  20.             }  
  21.             // 關閉緩衝閱讀器  
  22.             in.close();  
  23.         } catch (IOException e) { // Catch any IO exceptions.  
  24.             e.printStackTrace();  
  25.         }  
  26.     }  
  27. }  

4.java.IO層次體系結構

     在整個Java.io包中最重要的就是5個類和一個介面。5個類指的是File、OutputStream、InputStream、Writer、Reader;一個介面指的是Serializable.掌握了這些IO的核心操作那麼對於Java中的IO體系也就有了一個初步的認識了

      Java I/O主要包括如下幾個層次,包含三個部分:

   1.流式部分――IO的主體部分;

   2.非流式部分――主要包含一些輔助流式部分的類,如:File類、RandomAccessFile類和FileDescriptor等類;

   3.其他類--檔案讀取部分的與安全相關的類,如:SerializablePermission類,以及與本地作業系統相關的檔案系統的類,如:FileSystem類和Win32FileSystem類和WinNTFileSystem類。

   主要的類如下:

     1. File(檔案特徵與管理):用於檔案或者目錄的描述資訊,例如生成新目錄,修改檔名,刪除檔案,判斷檔案所在路徑等。

     2. InputStream(二進位制格式操作):抽象類,基於位元組的輸入操作,是所有輸入流的父類。定義了所有輸入流都具有的共同特徵。

     3. OutputStream(二進位制格式操作):抽象類。基於位元組的輸出操作。是所有輸出流的父類。定義了所有輸出流都具有的共同特徵。

     Java中字元是採用Unicode標準,一個字元是16位,即一個字元使用兩個位元組來表示。為此,JAVA中引入了處理字元的流。

     4. Reader(檔案格式操作):抽象類,基於字元的輸入操作。

     5. Writer(檔案格式操作):抽象類,基於字元的輸出操作。

     6. RandomAccessFile(隨機檔案操作):它的功能豐富,可以從檔案的任意位置進行存取(輸入輸出)操作

     Java中IO流的體系結構如圖:

     


5. 非流式檔案類--File類


在Java語言的java.io包中,由File類提供了描述檔案和目錄的操作與管理方法。但File類不是InputStream、OutputStream或Reader、Writer的子類,因為它不負責資料的輸入輸出,而專門用來管理磁碟檔案與目錄。

作用:File類主要用於命名檔案、查詢檔案屬性和處理檔案目錄。
  1. public    class   File   extends Object   
  2.     implements Serializable,Comparable  
  3. {}  

File類共提供了三個不同的建構函式,以不同的引數形式靈活地接收檔案和目錄名資訊。建構函式:
1)File (String   pathname)   
     例:File  f1=new File("FileTest1.txt"); //建立檔案物件f1,f1所指的檔案是在當前目錄下建立的FileTest1.txt
2)File (String  parent  ,  String child)
     例:File f2=new  File(“D:\\dir1","FileTest2.txt") ;//  注意:D:\\dir1目錄事先必須存在,否則異常
3)File (File    parent  , String child)
     例:File  f4=new File("\\dir3");
          File  f5=new File(f4,"FileTest5.txt");  //在如果 \\dir3目錄不存在使用f4.mkdir()先建立
        一個對應於某磁碟檔案或目錄的File物件一經建立, 就可以通過呼叫它的方法來獲得檔案或目錄的屬性。    
       1)public boolean exists( ) 判斷檔案或目錄是否存在
       2)public boolean isFile( ) 判斷是檔案還是目錄 
       3)public boolean isDirectory( ) 判斷是檔案還是目錄
       4)public String getName( ) 返回檔名或目錄名
       5)public String getPath( ) 返回檔案或目錄的路徑。
       6)public long length( ) 獲取檔案的長度 
       7)public String[ ] list ( ) 將目錄中所有檔名儲存在字串陣列中返回。 
       File類中還定義了一些對檔案或目錄進行管理、操作的方法,常用的方法有:
       1) public boolean renameTo( File newFile );    重新命名檔案
       2) public void delete( );   刪除檔案
       3)  public boolean mkdir( ); 建立目錄

例子:

  1. import java.io.File;  
  2. import java.io.IOException;  
  3. public class TestFile {  
  4.     public static void main(String args[]) throws IOException {  
  5.         File dir = new File("\\root");  
  6.         File f1 = new File(dir, "fileOne.txt");  
  7.         File f2 = new File(dir, "fileTwo.java");  
  8.         // 檔案物件建立後,指定的檔案或目錄不一定物理上存在  
  9.         if (!dir.exists())  
  10.             dir.mkdir();  
  11.         if (!f1.exists())  
  12.             f1.createNewFile();  
  13.         if (!f2.exists())  
  14.             f2.createNewFile();  
  15.         System.out.println("f1's AbsolutePath=  " + f1.getAbsolutePath());  
  16.         System.out.println("f1 Canread=" + f1.canRead());  
  17.         System.out.println("f1's len= " + f1.length());  
  18.         String[] FL;  
  19.         int count = 0;  
  20.         FL = dir.list();  
  21.         for (int i = 0; i < FL.length; i++) {  
  22.             count++;  
  23.             System.out.println(FL[i] + "is in \\root");  
  24.         }  
  25.         System.out.println("there are" + count + "file in //root");  
  26.     }  
  27.   
  28. }  

說明:File類的方法:
(1) exists()測試磁碟中指定的檔案或目錄是否存在
(2) mkdir()建立檔案物件指定的目錄(單層目錄)
(3) createNewFile()建立檔案物件指定的檔案

(4) list()返回目錄中所有檔名字串

6. Java.IO流類庫

1. io流的四個基本類

      java.io包中包含了流式I/O所需要的所有類。在java.io包中有四個基本類:InputStream、OutputStream及Reader、Writer類,它們分別處理位元組流和字元流:

基本資料流的I/O

輸入/輸出

位元組流

字元流

輸入流

Inputstream

Reader

輸出流

OutputStream

Writer


     Java中其他多種多樣變化的流均是由它們派生出來的:

      JDK1.4版本開始引入了新I/O類庫,它位於java.nio包中,新I/O類庫利用通道和緩衝區等來提高I/O操作的效率。

      在java.io包中, java.io.InputStream 表示位元組輸入流, java.io.OutputStream表示位元組輸出流,處於java.io包最頂層。這兩個類均為抽象類,也就是說它們不能被例項化,必須生成子類之後才能實現一定的功能。

1. io流的具體分類

一、按I/O型別來總體分類:

     1. Memory 1)從/向記憶體陣列讀寫資料: CharArrayReader、 CharArrayWriter、ByteArrayInputStream、ByteArrayOutputStream
                   2)從/向記憶體字串讀寫資料 StringReader、StringWriter、StringBufferInputStream
     2.Pipe管道  實現管道的輸入和輸出(程式間通訊): PipedReader、PipedWriter、PipedInputStream、PipedOutputStream
     3.File 檔案流。對檔案進行讀、寫操作 :FileReader、FileWriter、FileInputStream、FileOutputStream
     4. ObjectSerialization 物件輸入、輸出 :ObjectInputStream、ObjectOutputStream
     5.DataConversion資料流 按基本資料型別讀、寫(處理的資料是Java的基本型別(如布林型,位元組,整數和浮點數)):DataInputStream、DataOutputStream
     6.Printing 包含方便的列印方法 :PrintWriter、PrintStream
     7.Buffering緩衝  在讀入或寫出時,對資料進行快取,以減少I/O的次數:BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream
     8.Filtering 濾流,在資料進行讀或寫時進行過濾:FilterReader、FilterWriter、FilterInputStream、FilterOutputStream
     9.Concatenation合併輸入 把多個輸入流連線成一個輸入流 :SequenceInputStream
    10.Counting計數  在讀入資料時對行記數 :LineNumberReader、LineNumberInputStream
    11.Peeking Ahead 通過快取機制,進行預讀 :PushbackReader、PushbackInputStream
    12.Converting between Bytes and Characters 按照一定的編碼/解碼標準將位元組流轉換為字元流,或進行反向轉換(Stream到Reader,Writer的轉換類):InputStreamReader、OutputStreamWriter

二、按資料來源(去向)分類: 
1、File(檔案): FileInputStream, FileOutputStream, FileReader, FileWriter 
2、byte[]:ByteArrayInputStream, ByteArrayOutputStream 
3、Char[]: CharArrayReader, CharArrayWriter 
4、String: StringBufferInputStream, StringReader, StringWriter 
5、網路資料流:InputStream, OutputStream, Reader, Writer 

7. 位元組流InputStream/OutputStream

 1. InputStream抽象類 

      InputStream 為位元組輸入流,它本身為一個抽象類,必須依靠其子類實現各種功能,此抽象類是表示位元組輸入流的所有類的超類。 繼承自InputStream  的流都是向程式中輸入資料的,且資料單位為位元組(8bit);

InputStream是輸入位元組資料用的類,所以InputStream類提供了3種過載的read方法.Inputstream類中的常用方法: 
  (1) public abstract int read( ):讀取一個byte的資料,返回值是高位補0的int型別值。若返回值=-1說明沒有讀取到任何位元組讀取工作結束。
  (2) public int read(byte b[ ]):讀取b.length個位元組的資料放到b陣列中。返回值是讀取的位元組數。該方法實際上是呼叫下一個方法實現的 
  (3) public int read(byte b[ ], int off, int len):從輸入流中最多讀取len個位元組的資料,存放到偏移量為off的b陣列中。 
  (4) public int available( ):返回輸入流中可以讀取的位元組數。注意:若輸入阻塞,當前執行緒將被掛起,如果InputStream物件呼叫這個方法的話,它只會返回0,這個方法必須由繼承InputStream類的子類物件呼叫才有用, 
  (5) public long skip(long n):忽略輸入流中的n個位元組,返回值是實際忽略的位元組數, 跳過一些位元組來讀取 
  (6) public int close( ) :我們在使用完後,必須對我們開啟的流進行關閉. 

         主要的子類:

        

         1) FileInputStream把一個檔案作為InputStream,實現對檔案的讀取操作     
    2) ByteArrayInputStream:把記憶體中的一個緩衝區作為InputStream使用 
    3) StringBufferInputStream:把一個String物件作為InputStream 
    4) PipedInputStream:實現了pipe的概念,主要線上程中使用 
    5) SequenceInputStream:把多個InputStream合併為一個InputStream 

 2.OutputStream抽象類 

  OutputStream提供了3個write方法來做資料的輸出,這個是和InputStream是相對應的。 
  1. public void write(byte b[ ]):將引數b中的位元組寫到輸出流。 
  2. public void write(byte b[ ], int off, int len) :將引數b的從偏移量off開始的len個位元組寫到輸出流。 
  3. public abstract void write(int b) :先將int轉換為byte型別,把低位元組寫入到輸出流中。 
  4. public void flush( ) : 將資料緩衝區中資料全部輸出,並清空緩衝區。 
  5. public void close( ) : 關閉輸出流並釋放與流相關的系統資源。 

       主要的子類:

        

      1) ByteArrayOutputStream:把資訊存入記憶體中的一個緩衝區中 
      2) FileOutputStream:把資訊存入檔案中 
      3) PipedOutputStream:實現了pipe的概念,主要線上程中使用 
      4) SequenceOutputStream:把多個OutStream合併為一個OutStream 

流結束的判斷:方法read()的返回值為-1時;readLine()的返回值為null時。

3. 檔案輸入流: FileInputStream類

      FileInputStream可以使用read()方法一次讀入一個位元組,並以int型別返回,或者是使用read()方法時讀入至一個byte陣列,byte陣列的元素有多少個,就讀入多少個位元組。在將整個檔案讀取完成或寫入完畢的過程中,這麼一個byte陣列通常被當作緩衝區,因為這麼一個byte陣列通常扮演承接資料的中間角色。


作用:以檔案作為資料輸入源的資料流。或者說是開啟檔案,從檔案讀資料到記憶體的類。
使用方法(1)    
   File  fin=new File("d:/abc.txt"); 
  FileInputStream in=new FileInputStream( fin);

使用方法(2)
   FileInputStream  in=new  FileInputStream(“d: /abc.txt”);

程式舉例:
將InputFromFile.java的程式的內容顯示在顯示器上


  1. import java.io.IOException;  
  2. import java.io.FileInputStream;  
  3. ;  
  4. public class TestFile {  
  5.     public static void main(String args[]) throws IOException {  
  6.         try{      
  7.                FileInputStream rf=new   FileInputStream("InputFromFile.java");  
  8.                int n=512;   byte  buffer[]=new  byte[n];     
  9.                while((rf.read(buffer,0,n)!=-1)&&(n>0)){  
  10.                    System.out.println(new String(buffer) );  
  11.                 }  
  12.                 System.out.println();  
  13.                 rf.close();  
  14.         } catch(IOException  IOe){        
  15.               System.out.println(IOe.toString());  
  16.         }  
  17.   
  18.     }  
  19.   
  20. }  

4.檔案輸出流:FileOutputStream類

   作用:用來處理以檔案作為資料輸出目的資料流;或者說是從記憶體區讀資料入檔案

      FileOutputStream類用來處理以檔案作為資料輸出目的資料流;一個表示檔名的字串,也可以是File或FileDescriptor物件。 
  建立一個檔案流物件有兩種方法: 
  方式1: 
   File   f=new  File (“d:/myjava/write.txt ");
        FileOutputStream  out= new FileOutputStream (f);
  方式2: 
  FileOutputStream out=new FileOutputStream(“d:/myjava/write.txt "); 
  方式3:建構函式將 FileDescriptor()物件作為其引數。 
  FileDescriptor() fd=new FileDescriptor(); 
  FileOutputStream f2=new FileOutputStream(fd); 
  方式4:建構函式將檔名作為其第一引數,將布林值作為第二引數。 
  FileOutputStream f=new FileOutputStream("d:/abc.txt",true); 
  注意: (1)檔案中寫資料時,若檔案已經存在,則覆蓋存在的檔案;(2)的讀/寫操作結束時,應呼叫close方法關閉流。 

程式舉例:使用鍵盤輸入一段文章,將文章儲存在檔案write.txt中

  1. import java.io.IOException;  
  2. import java.io.FileOutputStream;  
  3. public class TestFile {  
  4.     public static void main(String args[]) throws IOException {  
  5.         try {  
  6.             System.out.println("please Input from      Keyboard");  
  7.             int count, n = 512;  
  8.             byte buffer[] = new byte[n];  
  9.             count = System.in.read(buffer);  
  10.             FileOutputStream wf = new FileOutputStream("d:/myjava/write.txt");  
  11.             wf.write(buffer, 0, count);  
  12.             wf.close(); // 當流寫操作結束時,呼叫close方法關閉流。  
  13.             System.out.println("Save to the write.txt");  
  14.         } catch (IOException IOe) {  
  15.             System.out.println("File Write Error!");  
  16.         }  
  17.     }  
  18.   
  19. }  

5. FileInputStream流和FileOutputStream的應用

利用程式將檔案file1.txt 拷貝到file2.txt中。
  1. import java.io.File;  
  2. import java.io.IOException;  
  3. import java.io.FileOutputStream;  
  4. import java.io.FileInputStream;  
  5.   
  6. public class TestFile {  
  7.     public static void main(String args[]) throws IOException {  
  8.         try {  
  9.             File inFile = new File("copy.java");  
  10.             File outFile = new File("copy2.java");  
  11.             FileInputStream finS = new FileInputStream(inFile);  
  12.             FileOutputStream foutS = new FileOutputStream(outFile);  
  13.             int c;  
  14.             while ((c = finS.read()) != -1) {  
  15.                 foutS.write(c);  
  16.             }  
  17.             finS.close();  
  18.             foutS.close();  
  19.         } catch (IOException e) {  
  20.             System.err.println("FileStreamsTest: " + e);  
  21.         }  
  22.     }  
  23.   
  24. }  

6. 緩衝輸入輸出流 BufferedInputStream/ BufferedOutputStream

        
      

       計算機訪問外部裝置非常耗時。訪問外存的頻率越高,造成CPU閒置的概率就越大。為了減少訪問外存的次數,應該在一次對外設的訪問中,讀寫更多的資料。為此,除了程式和流節點間交換資料必需的讀寫機制外,還應該增加緩衝機制。緩衝流就是每一個資料流分配一個緩衝區,一個緩衝區就是一個臨時儲存資料的記憶體。這樣可以減少訪問硬碟的次數,提高傳輸效率。

BufferedInputStream:當向緩衝流寫入資料時候,資料先寫到緩衝區,待緩衝區寫滿後,系統一次性將資料傳送給輸出裝置。

BufferedOutputStream :當從向緩衝流讀取資料時候,系統先從緩衝區讀出資料,待緩衝區為空時,系統再從輸入裝置讀取資料到緩衝區。

1)將檔案讀入記憶體:

BufferedInputStreamFileInputStream相接

  FileInputStream in=new  FileInputStream( “file1.txt ” );

  BufferedInputStream bin=new  BufferedInputStreamin); 

2)將記憶體寫入檔案:

BufferedOutputStream FileOutputStream相接

FileOutputStreamout=new FileOutputStream(“file1.txt”);

BufferedOutputStream  bin=new BufferedInputStream(out);


3)鍵盤輸入流讀到記憶體
BufferedReader標準的資料流相接 
 InputStreamReader sin=new InputStreamReader (System.in) ;
BufferedReader bin=new             BufferedReader(sin);
  1. import java.io.*;  
  2.   
  3. public class ReadWriteToFile {  
  4.     public static void main(String args[]) throws IOException {  
  5.         InputStreamReader sin = new InputStreamReader(System.in);  
  6.         BufferedReader bin = new BufferedReader(sin);  
  7.         FileWriter out = new FileWriter("myfile.txt");  
  8.         BufferedWriter bout = new BufferedWriter(out);  
  9.         String s;  
  10.         while ((s = bin.readLine()).length() > 0) {  
  11.             bout.write(s, 0, s.length());  
  12.         }  
  13.   
  14.     }  
  15. }  
程式說明:
從鍵盤讀入字元,並寫入到檔案中BufferedReader類的方法:String readLine()
作用:讀一行字串,以回車符為結束。
BufferedWriter類的方法:bout.write(String s,offset,len)
作用:從緩衝區將字串s從offset開始,len長度的字串寫到某處。

8. 字元流Writer/Reader

        Java中字元是採用Unicode標準,一個字元是16位,即一個字元使用兩個位元組來表示。為此,JAVA中引入了處理字元的流。

1. Reader抽象類

    用於讀取字元流的抽象類。子類必須實現的方法只有 read(char[], int, int) 和 close()。但是,多數子類將重寫此處定義的一些方法,以提供更高的效率和/或其他功能。

       

        1) FileReader :與FileInputStream對應  
           主要用來讀取字元檔案,使用預設的字元編碼,有三種建構函式: 
      (1)將檔名作為字串 :FileReader f=new FileReader(“c:/temp.txt”); 
      (2)建構函式將File物件作為其引數。 
              File f=new file(“c:/temp.txt”); 
              FileReader f1=new FileReader(f); 
     (3)  建構函式將FileDescriptor物件作為引數 
            FileDescriptor() fd=new FileDescriptor() 
            FileReader f2=new FileReader(fd); 
               (1) 用指定字元陣列作為引數:CharArrayReader(char[]) 
               (2) 將字元陣列作為輸入流:CharArrayReader(char[], int, int) 
          讀取字串,建構函式如下: public StringReader(String s); 
        2) CharArrayReader:與ByteArrayInputStream對應  
  3) StringReader : 與StringBufferInputStream對應 
  4) InputStreamReader 
        從輸入流讀取位元組,在將它們轉換成字元:Public inputstreamReader(inputstream is); 
  5) FilterReader: 允許過濾字元流 
        protected filterReader(Reader r); 
  6) BufferReader :接受Reader物件作為引數,並對其新增字元緩衝器,使用readline()方法可以讀取一行。 
     Public BufferReader(Reader r); 

      主要方法:

      (1)  public int read() throws IOException; //讀取一個字元,返回值為讀取的字元 

  (2)  public int read(char cbuf[]) throws IOException; /*讀取一系列字元到陣列cbuf[]中,返回值為實際讀取的字元的數量*/ 
  (3)  public abstract int read(char cbuf[],int off,int len) throws IOException; 
  /*讀取len個字元,從陣列cbuf[]的下標off處開始存放,返回值為實際讀取的字元數量,該方法必須由子類實現*/ 

2. Writer抽象類

     寫入字元流的抽象類。子類必須實現的方法僅有 write(char[], int, int)、flush() 和 close()。但是,多數子類將重寫此處定義的一些方法,以提供更高的效率和/或其他功能。 其子類如下:

    

      1) FileWrite: 與FileOutputStream對應  
  將字元型別資料寫入檔案,使用預設字元編碼和緩衝器大小。 
  Public FileWrite(file f); 
  
2)  chararrayWrite:與ByteArrayOutputStream對應 ,將字元緩衝器用作輸出。 
      Public CharArrayWrite(); 
  3) PrintWrite:生成格式化輸出 
      public PrintWriter(outputstream os); 
  4) filterWriter:用於寫入過濾字元流 
      protected FilterWriter(Writer w); 
  5) PipedWriter:與PipedOutputStream對應   

      6) StringWriter:無與之對應的以位元組為導向的stream  

      主要方法:

  (1)  public void write(int c) throws IOException; //將整型值c的低16位寫入輸出流 
  (2)  public void write(char cbuf[]) throws IOException; //將字元陣列cbuf[]寫入輸出流 
  (3)  public abstract void write(char cbuf[],int off,int len) throws IOException; //將字元陣列cbuf[]中的從索引為off的位置處開始的len個字元寫入輸出流 
  (4)  public void write(String str) throws IOException; //將字串str中的字元寫入輸出流 
  (5)  public void write(String str,int off,int len) throws IOException; //將字串str 中從索引off開始處的len個字元寫入輸出流 
  (6)  flush( ) //刷空輸出流,並輸出所有被快取的位元組。 
  (7)close()    關閉流 public abstract void close() throws IOException

3 .InputStream與Reader差別 OutputStream與Writer差別

InputStream和OutputStream類處理的是位元組流,資料流中的最小單位是位元組(8個bit)
Reader與Writer處理的是字元流,在處理字元流時涉及了字元編碼的轉換問題

  1. import java.io.*;  
  2. public class EncodeTest {  
  3.     private static void readBuff(byte [] buff) throws IOException {  
  4.        ByteArrayInputStream in =new ByteArrayInputStream(buff);  
  5.         int data;  
  6.         while((data=in.read())!=-1)   System.out.print(data+"  ");  
  7.         System.out.println();     in.close();     }  
  8.   
  9.    public static void main(String args[]) throws IOException {  
  10.        System.out.println("記憶體中採用unicode字元編碼:" );  
  11.        char   c='好';  
  12.        int lowBit=c&0xFF;     int highBit=(c&0xFF00)>>8;  
  13.        System.out.println(""+lowBit+"   "+highBit);  
  14.        String s="好";  
  15.        System.out.println("本地作業系統預設字元編碼:");  
  16.        readBuff(s.getBytes());  
  17.        System.out.println("採用GBK字元編碼:");  
  18.        readBuff(s.getBytes("GBK"));  
  19.        System.out.println("採用UTF-8字元編碼:");        
  20.        readBuff(s.getBytes("UTF-8"));      }  
  21. }  

Reader類能夠將輸入流中採用其他編碼型別的字元轉換為Unicode字元,然後在記憶體中為其分配記憶體
Writer類能夠將記憶體中的Unicode字元轉換為其他編碼型別的字元,再寫到輸出流中。

9. IOException異常類的子類

1.public class  EOFException :
   非正常到達檔案尾或輸入流尾時,丟擲這種型別的異常。
2.public class FileNotFoundException:
   當檔案找不到時,丟擲的異常。
3.public class InterruptedIOException:

   當I/O操作被中斷時,丟擲這種型別的異常。








通過資料流、序列化和檔案系統提供系統輸入和輸出。

Java把這些不同來源和目標的資料都統一抽象為資料流。Java語言的輸入輸出功能是十分強大而靈活的,美中不足的是看上去輸入輸出的程式碼並不是很簡潔,因為你往往需要包裝許多不同的物件。

在Java類庫中,IO部分的內容是很龐大的,因為它涉及的領域很廣泛:標準輸入輸出,檔案的操作,網路上的資料流,字串流,物件流,zip檔案流。

1.1、Java流的分類
按流向分:
輸入流: 程式可以從中讀取資料的流。
輸出流: 程式能向其中寫入資料的流。
按資料傳輸單位分:
位元組流: 以位元組為單位傳輸資料的流
字元流: 以字元為單位傳輸資料的流
按功能分:
節點流: 用於直接操作目標裝置的流
過濾流: 是對一個已存在的流的連結和封裝,通過對資料進行處理為程式提供功能強大、靈活的讀寫功能。
1.2、java.io常用類

JDK所提供的所有流類位於java.io包中,都分別繼承自以下四種抽象流類:

InputStream:繼承自InputStream的流都是用於向程式中輸入資料的,且資料單位都是位元組(8位)。
OutputSteam:繼承自OutputStream的流都是程式用於向外輸出資料的,且資料單位都是位元組(8位)。
Reader:繼承自Reader的流都是用於向程式中輸入資料的,且資料單位都是字元(16位)。
Writer:繼承自Writer的流都是程式用於向外輸出資料的,且資料單位都是字元(16位)。

java語言的輸入輸出功能是十分強大而靈活的,美中不足的是看上去輸入輸出的程式碼並不是很簡潔,因為你往往需要包裝許多不同的物件。在Java類庫中,IO部分的內容是很龐大的,因為它涉及的領域很廣泛:標準輸入輸出,檔案的操作,網路上的資料流,字串流,物件流,zip檔案流....本文的目的是為大家做一個簡要的介紹。

  流是一個很形象的概念,當程式需要讀取資料的時候,就會開啟一個通向資料來源的流,這個資料來源可以是檔案,記憶體,或是網路連線。類似的,當程式需要寫入資料的時候,就會開啟一個通向目的地的流。這時候你就可以想象資料好像在這其中“流”動一樣,如下圖:

                           

                               

 Java中的流分為兩種,一種是位元組流,另一種是字元流,分別由四個抽象類來表示(每種流包括輸入和輸出兩種所以一共四個):InputStream,OutputStream,Reader,Writer。Java中其他多種多樣變化的流均是由它們派生出來的:

stream代表的是任何有能力產出資料的資料來源,或是任何有能力接收資料的接收源。在Java的IO中,所有的stream(包括Inputstream和Out stream)都包括兩種型別:

  (1)位元組流

  表示以位元組為單位從stream中讀取或往stream中寫入資訊,即io包中的inputstream類和outputstream類的派生類。通常用來讀取二進位制資料,如圖象和聲音。

  (2)字元流

  以Unicode字元為導向的stream,表示以Unicode字元為單位從stream中讀取或往stream中寫入資訊。

  區別:

  Reader和Writer要解決的,最主要的問題就是國際化。原先的I/O類庫只支援8位的位元組流,因此不可能很好地處理16位的Unicode字元流。Unicode是國際化的字符集(更何況Java內建的char就是16位的Unicode字元),這樣加了Reader和Writer之後,所有的I/O就都支援Unicode了。此外新類庫的效能也比舊的好。

  但是,Read和Write並不是取代InputStream和OutputStream,有時,你還必須同時使用"基於byte的類"和"基於字元的類"。為此,它還提供了兩個"介面卡(adapter)"類。InputStreamReader負責將InputStream轉化成Reader,而OutputStreamWriter則將OutputStream轉化成Writer。

  一.流的層次結構

  定義:

  (1)       java將讀取資料物件成為輸入流,能向其寫入的物件叫輸出流。結構圖如下:

                                                輸入流

 

                                                 輸出流

 

 二.InputStream類

  inputstream類和outputstream類都為抽象類,不能建立物件,可以通過子類來例項化。

  InputStream是輸入位元組資料用的類,所以InputStream類提供了3種過載的read方法.Inputstream類中的常用方法:

  (1)       public abstract int read( ):讀取一個byte的資料,返回值是高位補0的int型別值。

  (2)       public int read(byte b[ ]):讀取b.length個位元組的資料放到b陣列中。返回值是讀取的位元組數。該方法實際上是呼叫下一個方法實現的

  (3)       public int read(byte b[ ], int off, int len):從輸入流中最多讀取len個位元組的資料,存放到偏移量為off的b陣列中。

  (4)       public int available( ):返回輸入流中可以讀取的位元組數。注意:若輸入阻塞,當前執行緒將被掛起,如果InputStream物件呼叫這個方法的話,它只會返回0,這個方法必須由繼承InputStream類的子類物件呼叫才有用,

  (5)       public long skip(long n):忽略輸入流中的n個位元組,返回值是實際忽略的位元組數, 跳過一些位元組來讀取

  (6)       public int close( ) :我們在使用完後,必須對我們開啟的流進行關閉.

  三.OutputStream類

  OutputStream提供了3個write方法來做資料的輸出,這個是和InputStream是相對應的。

  1. public void write(byte b[ ]):將引數b中的位元組寫到輸出流。

  2. public void write(byte b[ ], int off, int len) :將引數b的從偏移量off開始的len個位元組寫到輸出流。

  3. public abstract void write(int b) :先將int轉換為byte型別,把低位元組寫入到輸出流中。

  4. public void flush( ) : 將資料緩衝區中資料全部輸出,並清空緩衝區。

  5. public void close( ) : 關閉輸出流並釋放與流相關的系統資源。

  注意:

  1. 上述各方法都有可能引起異常。

  2. InputStream和OutputStream都是抽象類,不能建立這種型別的物件。

  四.FileInputStream類

  FileInputStream類是InputStream類的子類,用來處理以檔案作為資料輸入源的資料流。使用方法:

  方式1:

  File fin=new File("d:/abc.txt");

  FileInputStream in=new FileInputStream(fin);

  方式2:

  FileInputStream in=new

  FileInputStream("d: /abc.txt");

  方式3:

  建構函式將 FileDescriptor()物件作為其引數。

  FileDescriptor() fd=new FileDescriptor();

  FileInputStream f2=new FileInputStream(fd);

  五.FileOutputStream類

  FileOutputStream類用來處理以檔案作為資料輸出目的資料流;一個表示檔名的字串,也可以是File或FileDescriptor物件。

  建立一個檔案流物件有兩種方法:

  方式1:

  File f=new File("d:/abc.txt");

  FileOutputStream out=new FileOutputStream (f);

  方式2:

  FileOutputStream out=new

  FileOutputStream("d:/abc.txt");

  方式3:建構函式將 FileDescriptor()物件作為其引數。

  FileDescriptor() fd=new FileDescriptor();

  FileOutputStream f2=new FileOutputStream(fd);

方式4:建構函式將檔名作為其第一引數,將布林值作為第二引數。

  FileOutputStream f=new FileOutputStream("d:/abc.txt",true);

  注意:

  (1)檔案中寫資料時,若檔案已經存在,則覆蓋存在的檔案;(2)的讀/寫操作結束時,應呼叫close方法關閉流。

  舉例:2-1

  六.File類

  File類與InputStream / OutputStream類同屬於一個包,它不允許訪問檔案內容。

  File類主要用於命名檔案、查詢檔案屬性和處理檔案目錄。

  舉例:2-2

  七.從一個流構造另一個流

  java的流類提供了結構化方法,如,底層流和高層過濾流。

  而高層流不是從輸入裝置讀取,而是從其他流讀取。同樣高層輸出流也不是寫入輸出裝置,而是寫入其他流。

  使用"分層物件(layered objects)",為單個物件動態地,透明地新增功能的做法,被稱為Decorator Pattern。Decorator模式要求所有包覆在原始物件之外的物件,都必須具有與之完全相同的介面。這使得decorator的用法變得非常的透明--無論物件是否被decorate過,傳給它的訊息總是相同的。這也是Java I/O類庫要有"filter(過濾器)"類的原因:抽象的"filter"類是所有decorator的基類。Decorator模式常用於如下的情形:如果用繼承來解決各種需求的話,類的數量會多到不切實際的地步。Java的I/O類庫需要提供很多功能的組合,於是decorator模式就有了用武之地。

  為InputStream和OutputStream定義decorator類介面的類,分別是FilterInputStream和FilterOutputStream。

 

FilterInputStream的種類

 

 

 

 

 

功能

 

 

建構函式的引數

 

 

 

 

用法

 

 

 

 

DataInputStream

 

 

與DataOutputStream配合使用,這樣你就能以一種"可攜帶的方式(portable fashion)"從流裡讀取primitives了(int,char,long等)

 

 

InputStream

 

 

 

 

包含了一整套讀取primitive資料的介面。

 

 

 

 

BufferedInputStream

 

 

用這個類來解決"每次要用資料的時候都要進行物理讀取"的問題。你的意思是"用緩衝區。"

 

 

InputStream,以及可選的緩衝區的容量

 

 

 

 

它本身並不提供介面,只是提供一個緩衝區。需要連到一個"有介面的物件(interface object)"。

 

 

 

 

LineNumberInputStream

 

 

跟蹤輸入流的行號;有getLineNumber( )和setLineNumber(int)方法

 

 

InputStream

 

 

 

 

只是加一個行號,所以還得連一個"有介面的物件"。

 

 

 

 

PushbackInputStream

 

 

有一個"彈壓單位元組"的緩衝區(has a one byte push-back buffer),這樣你就能把最後讀到的那個位元組再壓回去了。

 

 

InputStream

 

 

 

 

主要用於編譯器的掃描程式。可能是為支援Java的編譯器而設計的。用的機會不多。

 

FilterOutputStream的種類

 

 

 

 

 

功能

 

 

建構函式的引數

 

 

 

 

用法

 

 

 

 

DataOutputStream

 

 

與DataInputStream配合使用,這樣你就可以用一種"可攜帶的方式(portable fashion)"往流裡寫primitive了(int, char, long,等)

 

 

OutputStream

 

 

 

 

包括寫入primitive資料的全套介面。

 

 

 

 

PrintStream

 

 

負責生成帶格式的輸出(formatted output)。DataOutputStrem負責資料的儲存,而PrintStream負責資料的顯示。

 

 

一個OutputStream以及一個可選的boolean值。這個boolean值表示,要不要清空換行符後面的緩衝區。

 

 

 

 

應該是OutputStream物件的最終包覆層。用的機會很多。

 

 

 

 

BufferedOutputStream

 

 

用 這個類解決"每次往流裡寫資料,都要進行物理操作"的問題。也就是說"用緩衝區"。用flush( )清空緩衝區。

 

 

OutputStream, 以及一個可選的緩衝區大小

 

 

 

 

本身並不提供介面,只是加了一個緩衝區。需要連結一個有介面的物件。

  DataInputStream類物件可以讀取各種型別的資料。

  DataOutputStream類物件可以寫各種型別的資料;

  建立這兩類物件時,必須使新建立的物件指向建構函式中的引數物件。例如:

  FileInputStream in=new FileInputStream("d:/abc.txt");

  DataInputStream din=new DataInputStream(in);

  7.2BufferInputStream和bufferOutputStream

  允許程式在不降低系統效能的情況下一次一個位元組的從流中讀取資料。

  BufferInputstream定義了兩種建構函式

  (1)       BufferInputStream b= new BufferInputstream(in);

  (2)       BufferInputStream b=new BufferInputStream(in,size)

  第二個參數列示指定緩衝器的大小。

  同樣BufferOutputStream也有兩種建構函式。一次一個位元組的向流中寫資料。

  7.3printstream

  用於寫入文字或基本型別

  兩種建構函式方法:

  PrintStream ps=new PrintStream(out);

  PrintStream ps=new PrintStream(out, autoflush)

  第二個引數為布林值,控制每次輸出換行符時java是否重新整理輸出流。

  八.字元流的讀取和寫入

  java.io.Reader 和 java.io.InputStream 組成了 Java 輸入類。Reader 用於讀入16位字元,也就是 Unicode 編碼的字元;而 InputStream 用於讀入 ASCII 字元和二進位制資料。

 

                                    Reader 體系結構

(1)       FileReader

  FileReader主要用來讀取字元檔案,使用預設的字元編碼,有三種建構函式:

  --將檔名作為字串

  FileReader f=new FileReader(“c:/temp.txt”);

  --建構函式將File物件作為其引數。

  File f=new file(“c:/temp.txt”);

  FileReader f1=new FileReader(f);

  --建構函式將FileDescriptor物件作為引數

  FileDescriptor() fd=new FileDescriptor()

  FileReader f2=new FileReader(fd);

  (2)    charArrayReader

  將字元陣列作為輸入流,建構函式為:

  public CharArrayReader(char[] ch);

  (3)    StringReader

  讀取字串,建構函式如下:

  public StringReader(String s);

  (4)    InputStreamReader

  從輸入流讀取位元組,在將它們轉換成字元。

  Public inputstreamReader(inputstream is);

  (5)    FilterReader

  允許過濾字元流

  protected filterReader(Reader r);

(6)    BufferReader

  接受Reader物件作為引數,並對其新增字元緩衝器,使用readline()方法可以讀取一行。

  Public BufferReader(Reader r);

                                      Writer類體系結構

(1)       FileWrite

  將字元型別資料寫入檔案,使用預設字元編碼和緩衝器大小。

  Public FileWrite(file f);

  (2)chararrayWrite()

  將字元緩衝器用作輸出。

  Public CharArrayWrite();

  (3)    PrintWrite

  生成格式化輸出

  public PrintWriter(outputstream os);

  (4)    filterWriter

  用於寫入過濾字元流

  protected FilterWriter(Writer w);

 

FilterOutputStream的種類

 

 

 

 

 

功能

 

 

建構函式的引數

 

 

 

 

用法

 

 

 

 

DataOutputStream

 

 

與DataInputStream配合使用,這樣你就可以用一種"可攜帶的方式(portable fashion)"往流裡寫primitive了(int, char, long,等)

 

 

OutputStream

 

 

 

 

包括寫入primitive資料的全套介面。

 

 

 

 

PrintStream

 

 

負責生成帶格式的輸出(formatted output)。DataOutputStrem負責資料的儲存,而PrintStream負責資料的顯示。

 

 

一個OutputStream以及一個可選的boolean值。這個boolean值表示,要不要清空換行符後面的緩衝區。

 

 

 

 

應該是OutputStream物件的最終包覆層。用的機會很多。

 

 

 

 

BufferedOutputStream

 

 

用 這個類解決"每次往流裡寫資料,都要進行物理操作"的問題。也就是說"用緩衝區"。用flush( )清空緩衝區。

 

 

OutputStream, 以及一個可選的緩衝區大小

 

 

 

 

本身並不提供介面,只是加了一個緩衝區。需要連結一個有介面的物件。

  DataInputStream類物件可以讀取各種型別的資料。

  DataOutputStream類物件可以寫各種型別的資料;

  建立這兩類物件時,必須使新建立的物件指向建構函式中的引數物件。例如:

  FileInputStream in=new FileInputStream("d:/abc.txt");

  DataInputStream din=new DataInputStream(in);

  7.2BufferInputStream和bufferOutputStream

  允許程式在不降低系統效能的情況下一次一個位元組的從流中讀取資料。

  BufferInputstream定義了兩種建構函式

  (1)       BufferInputStream b= new BufferInputstream(in);

  (2)       BufferInputStream b=new BufferInputStream(in,size)

  第二個參數列示指定緩衝器的大小。

  同樣BufferOutputStream也有兩種建構函式。一次一個位元組的向流中寫資料。

  7.3printstream

  用於寫入文字或基本型別

  兩種建構函式方法:

  PrintStream ps=new PrintStream(out);

  PrintStream ps=new PrintStream(out, autoflush)

  第二個引數為布林值,控制每次輸出換行符時java是否重新整理輸出流


相關文章