Java的IO總結

非流式文件類--File類

  從定義看,File類是Object的直接子類,同時它繼承了Comparable接口可以進行數組的排序。

File類的操作包括文件的創建、刪除、重命名、得到路徑、創建時間等,以下是文件操作常用的函數。

 

 

File類是對文件系統中文件以及文件夾進行封裝的對象,可以通過對象的思想來操作文件和文件夾。File類保存文件或目錄的各種元數據信息,包括文件名、文件長度、最後修改時間、是否可讀、獲取當前文件的路徑名,判斷指定文件是否存在、獲得當前目錄中的文件列表,創建、刪除文件和目錄等方法。 

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( ); 創建目錄

流簡單概念介紹

在Java程序中,對於數據的輸入/輸出操作以"流" (stream) 方式進行;
J2SDK提供了各種各樣的"流"類,用以獲取不同種類的數據;程序中通過標準的方法輸入或輸出數據。
Java的流類型一般位於java.io包中


流的方向:
輸入流:數據源到程序(InputStream、Reader讀進來)
輸出流:程序到目的地(OutPutStream、Writer寫出去)


處理數據單元:
字節流:按照字節讀取數據(InputStream、OutputStream)
字符流:按照字符讀取數據(Reader、Writer)


功能不同:
節點流:可以直接從數據源或目的地讀寫數據。
處理流(包裝流):不直接連接到數據源或目的地,是其他流進行封裝。目的主要是簡化操作和提高性能.


節點流和處理流的關係:
節點流處於io操作的第一線,所有操作必須通過他們進行;
處理流可以對其他流進行處理(提高效率或操作靈活性).

字節流基類

1).InputStream

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

 常用方法:

    // 從輸入流中讀取數據的下一個字節
    abstract int read()
    // 從輸入流中讀取一定數量的字節,並將其存儲在緩衝區數組 b中
    int read(byte[] b)
    // 將輸入流中最多 len 個數據字節讀入 byte 數組
    int read(byte[] b, int off, int len)


    // 跳過和丟棄此輸入流中數據的 n個字節
    long skip(long n)

    // 關閉此輸入流並釋放與該流關聯的所有系統資源
    void close()

2).OutputStream

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

 常用方法:
    // 將 b.length 個字節從指定的 byte 數組寫入此輸出流
    void write(byte[] b)
    // 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此輸出流
    void write(byte[] b, int off, int len)
    // 將指定的字節寫入此輸出流
    abstract void write(int b)

    // 關閉此輸出流並釋放與此流有關的所有系統資源
    void close()

    // 刷新此輸出流並強制寫出所有緩衝的輸出字節
    void flush()

字節流FileInputStream和FileOuputStream

介紹

1).FileInputStream

FileInputStream:字節文件輸入流,從文件系統中的某個文件中獲得輸入字節,用於讀取諸如圖像數據之類的原始字節流。

 構造方法:
    // 通過打開一個到實際文件的連接來創建一個FileInputStream,該文件通過文件系統中的File對象file指定
    FileInputStream(File file)
    // 通過打開一個到實際文件的連接來創建一個FileInputStream,該文件通過文件系統中的路徑name指定
    FileInputStream(String name)

 常用方法:覆蓋和重寫了父類的的常用方法。

2).FileOutputStream

FileOutputStream:字節文件輸出流是用於將數據寫入到File,從程序中寫入到其他位置。

 構造方法:
    // 創建一個向指定File對象表示的文件中寫入數據的文件輸出流
    FileOutputStream(File file)
    // 創建一個向指定File對象表示的文件中寫入數據的文件輸出流
    FileOutputStream(File file, boolean append)
    // 創建一個向具有指定名稱的文件中寫入數據的輸出文件流
    FileOutputStream(String name)
    // 創建一個向具有指定name的文件中寫入數據的輸出文件流
    FileOutputStream(String name, boolean append)

 常用方法:覆蓋和重寫了父類的的常用方法。

文件複製

(熟悉操作):

/**
* 功能:文件複製
* 技能:FileInputStream和FileOuputStream
*
* 總結
* 如何創建流
*  InputStream is = new FileInputStream(new File("e:/readme.txt"));
*  OutputStream os = new FileOutputStream(new File("e:\\readme2.txt"));
*
*
* 流使用完畢一定要關閉
*
* 如何使用流
*   n = is.read();
*   os.write(n);
*        
* 缺點:
* @author Administrator
*
*/
public class TestCopy1 {

       public static void main(String[] args) throws IOException {
               //創建一個輸入流和輸出流
//                File file = new File("e:/readme.txt");
//                InputStream is = new FileInputStream(file);
               InputStream is = new FileInputStream(new File("e:/readme.txt"));
//                File file2 = new File("e:\readme2.txt");
//                OutputStream os = new FileOutputStream(file2);
               OutputStream os = new FileOutputStream(new File("e:\\readme2.txt"));
               
               //使用輸入流和輸出流完成文件複製
               int n;//中轉站,比較小(水杯)
               
               //讀一個字節
               n = is.read();//從輸入流讀取一個字節的內容賦給n
               while(n != -1){//沒有到達末尾
                       //寫一個字節
                       os.write(n);
                       //輸出一個字節
                       //System.out.print((char)n);
                       
                       //讀一個字節
                       n = is.read();
               }        
               
               //關閉輸入流和輸出流
               is.close();
               os.close();

       }

}

正式標準實現:(一次1024)

/**
* 功能:文件複製
* 技能:FileInputStream和FileOuputStream
*
* 總結
* 如何創建流
*  InputStream is = new FileInputStream(new File("e:/readme.txt"));
*  OutputStream os = new FileOutputStream(new File("e:\\readme2.txt"));
*
*
* 流使用完畢一定要關閉
*
* 如何使用流
*   n = is.read();
*         os.write(n);
*        
* 缺點:中轉站太小
*
* @author Administrator
*
*/
public class TestCopy2 {

       public static void main(String[] args) throws IOException {
               //創建輸入流和輸出流
               InputStream fis = new FileInputStream("e:/JDK_API_1_6_zh_CN.CHM");
               OutputStream fos = new FileOutputStream("e:/JDK_API_1_6_zh_CN2.CHM");
               //使用輸入流和輸出流
               byte [] buf = new byte[1024];
               //讀一次
               int len = fis.read(buf);//將源文件的內容寫入到buf中,返回真實讀取的字節數
               while(len != -1){
                       //寫一次
                       //fos.write(buf);//寫1024
                       fos.write(buf, 0, len);
                       //讀一次
                       len = fis.read(buf);
               }
               
               
               //關閉輸入流和輸出流
               fis.close();
               fos.close();
       }

}

 

字符流Reader和Writer

字符流基類

1).Reader

Reader:讀取字符流的抽象類.

  常用方法:
    // 讀取單個字符
    int read()
    // 將字符讀入數組
    int read(char[] cbuf)
    // 將字符讀入數組的某一部分
    abstract int read(char[] cbuf, int off, int len)
    // 跳過字符
    long skip(long n)

    // 關閉該流並釋放與之關聯的所有資源
    abstract void close()

2).Writer

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

 常用方法:
    // 寫入字符數組
     void write(char[] cbuf)
    // 寫入字符數組的某一部分
    abstract void write(char[] cbuf, int off, int len)
    // 寫入單個字符
    void write(int c)
    // 寫入字符串
    void write(String str)
    // 寫入字符串的某一部分
    void write(String str, int off, int len)

    // 將指定字符添加到此 writer
    Writer append(char c)
    // 將指定字符序列添加到此 writer
    Writer append(CharSequence csq)
    // 將指定字符序列的子序列添加到此 writer.Appendable
    Writer append(CharSequence csq, int start, int end)

    // 關閉此流,但要先刷新它
    abstract void close()
    // 刷新該流的緩衝
    abstract void flush()

文件複製:

熟悉操作     

/**
*
* 1.字節流可以讀寫任何文件(文本文件、二進制文件(音頻視頻圖片 chm))
*         字符流只可以讀寫文本文件(word不是文本文件)
*   但是字符串處理非英文字符文本文件非常方便
*  
* 2.其實只有字節流,沒有字符流
*         字符流底層使用的還是字節流
*                Java在字節流基礎上提供了字符流,給編程帶來便利
*
* 3.字符流如何是英文字符還是中文字符
*                英文佔一個字節,最高位是0   0111 0011
*                中文佔兩個字節,最高位是1   1011 1011 1001 1101
*
* 4.缺陷:沒有進行異常處理
*
*
* @author Administrator
*
*/
public class TestCopy1 {

       public static void main(String[] args) throws IOException {
               //創建輸入流和輸出流
               Reader fr = new FileReader(new File("e:/readme.txt"));
               Writer fw = new FileWriter(new File("e:\\readme2.txt"));//默認是false 覆蓋
               //Writer fw = new FileWriter(new File("e:\\readme2.txt"), true);
               //使用輸入流和輸出流
//                //讀一個字符
//                int ch = fr.read();        //中轉站是一個字符
//                while(ch !=-1){
//                        //寫一個字符
//                        fw.write(ch);
//                        //輸出
//                        System.out.println((char)ch);
//                        //讀一個字符
//                        ch = fr.read();        
//                }        
               
               char cbuf [] = new char[1024];
               //讀一次
               int len = fr.read(cbuf);//將讀取的內容放入cbuf數組,返回的是真正讀取的字符個數
               while(len != -1){
                       //寫一次
                       //fw.write(cbuf);
                       fw.write(cbuf, 0, len);
                       //讀一次
                       len = fr.read(cbuf);                        
               }                
               //關閉輸入流和輸出流
               fr.close();
               fw.close();
       }

}

加上缺陷處理完整版:

/**
*
* 1.字節流可以讀寫任何文件(文本文件、二進制文件(音頻視頻圖片 chm))
*         字符流只可以讀寫文本文件(word不是文本文件)
*   但是字符串處理非英文字符文本文件非常方便
*  
* 2.其實只有字節流,沒有字符流
*         字符流底層使用的還是字節流
*                Java在字節流基礎上提供了字符流,給編程帶來便利
*
* 3.字符流如何是英文字符還是中文字符
*                英文佔一個字節,最高位是0   0111 0011
*                中文佔兩個字節,最高位是1   1011 1011 1001 1101
*
* 4.缺陷:沒有進行異常處理
*
*
* @author Administrator
*
*/
public class TestCopy2 {

       public static void main(String[] args){
               
               Reader fr = null;
               Writer fw = null;
               try {
                       //創建輸入流和輸出流
                       fr = new FileReader(new File("e:/readme.txt"));
                       fw = new FileWriter(new File("e:\\readme2.txt"));//默認是false 覆蓋

                       
                       char cbuf [] = new char[1024];
                       //讀一次
                       int len = fr.read(cbuf);//將讀取的內容放入cbuf數組,返回的是真正讀取的字符個數
                       while(len != -1){
                               //寫一次
                               //fw.write(cbuf);
                               fw.write(cbuf, 0, len);
                               //讀一次
                               len = fr.read(cbuf);                        
                       }
               } catch (FileNotFoundException e) {
                       e.printStackTrace();
               } catch (IOException e) {
                       e.printStackTrace();
               }finally{
                       //關閉輸入流和輸出流
                       try {
                               if(fr != null){
                                       fr.close();
                               }                                
                       } catch (IOException e) {
                               e.printStackTrace();
                       }
                       
                       try {
                               if(fw != null){
                                       fw.close();
                               }                                
                       } catch (IOException e) {
                               e.printStackTrace();
                       }
                       
               }
       }

}

緩衝字節流BufferedInputStream和BufferedOuputStream

介紹

BufferedInputStream

字節緩衝輸入流,提高了讀取效率。

     構造方法:
     // 創建一個 BufferedInputStream並保存其參數,即輸入流in,以便將來使用。
     BufferedInputStream(InputStream in)
     // 創建具有指定緩衝區大小的 BufferedInputStream並保存其參數,即輸入流in以便將來使用
     BufferedInputStream(InputStream in, int size)

.BufferedOutputStream

字節緩衝輸出流,提高了寫出效率。

     構造方法:
     // 創建一個新的緩衝輸出流,以將數據寫入指定的底層輸出流
     BufferedOutputStream(OutputStream out)
     // 創建一個新的緩衝輸出流,以將具有指定緩衝區大小的數據寫入指定的底層輸出流
     BufferedOutputStream(OutputStream out, int size)

     常用方法:
     // 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此緩衝的輸出流
     void write(byte[] b, int off, int len)
     // 將指定的字節寫入此緩衝的輸出流
     void write(int b)
     // 刷新此緩衝的輸出流
     void flush()

文件複製

/**
* 功能:文件複製
* 技能:BufferedInputStream和BufferedOuputStream
*
*
* 1.節點流和處理流
*        節點流   FileInputStream  FileOutputStream
*   處理流  BufferedInputStream  BufferedOutputStream
*  
* 2.處理流的好處
*        好處1:提供了性能
*
*
* 3.如何創建處理流
*                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("e:/JDK_API_1_6_zh_CN.CHM")));
               BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("e:\\JDK_API_1_6_zh_CN2.CHM")));
               

* 4.關閉流:只要關閉高層流即可,底層流可以不關閉
*        關閉高層流的會關閉底層流
*
*
* 5.何時將輸出緩衝區的內容更新到文件中(刷新 flush)
*
*        1.緩衝區滿了,自動刷新
*  2.關閉輸出流時,會先刷新再關閉
*  3.不滿的時候也可以手動刷新  
*     bos.flush();
*
*
*   public void close() throws IOException {
       try {
         flush();//刷新緩衝區
       } catch (IOException ignored) {
       }
       out.close(); //關閉底層流
   }
*
* @author Administrator
*
*/
public class TestCopy1 {

       public static void main(String[] args) throws IOException {
               //創建一個輸入流和輸出流
//                InputStream is = new FileInputStream(new File("e:/JDK_API_1_6_zh_CN.CHM"));
//                OutputStream os = new FileOutputStream(new File("e:\\JDK_API_1_6_zh_CN2.CHM"));
//                BufferedInputStream bis = new BufferedInputStream(is);//默認輸入緩衝區大小8192
//                BufferedOutputStream bos = new BufferedOutputStream(os);//默認輸出緩衝區大小8192
               
               BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("e:/JDK_API_1_6_zh_CN.CHM")));
               BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("e:\\JDK_API_1_6_zh_CN2.CHM")));
               
               //使用輸入流和輸出流完成文件複製
               int n;//中轉站,比較小(水杯)
               
               //讀一個字節
               n = bis.read();//從輸入流讀取一個字節的內容賦給n
               while(n != -1){//沒有到達末尾
                       //寫一個字節
                       bos.write(n);
                                               
                       //讀一個字節
                       n = bis.read();
               }        
               
               
               //關閉輸入流和輸出流
               bis.close();
               bos.close();

       }

}

緩衝字符流BufferedReader和BufferedWriter

 

1).BufferedReader

BufferedReader:字符緩衝流,從字符輸入流中讀取文本,緩衝各個字符,從而實現字符、數組和行的高效讀取。

 構造方法:
    // 創建一個使用默認大小輸入緩衝區的緩衝字符輸入流
    BufferedReader(Reader in)
    // 創建一個使用指定大小輸入緩衝區的緩衝字符輸入流
    BufferedReader(Reader in, int sz)
 特有方法:
    // 讀取一個文本行
    String readLine()

2).BufferedWriter

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

 構造方法:
    // 創建一個使用默認大小輸出緩衝區的緩衝字符輸出流
    BufferedWriter(Writer out)
    // 創建一個使用給定大小輸出緩衝區的新緩衝字符輸出流
    BufferedWriter(Writer out, int sz)
 特有方法:
    // 寫入一個行分隔符
    void newLine() 

 

文件複製

/**
* 按行讀取文件並複製
*
* 只要文本文件纔有行的概念  字符流
* 提高速度:緩衝流
* BufferedReader和BufferedWriter
*
*
*
* 1.處理流的好處
*        1.提高性能
*  2.簡化操作
*  
* 2.readLine的實現原理
*        底層還是按照字符一個個讀取, 由於採用了緩衝區,性能是提高
*  基本思路:
        *  StringBuilder  builder = new StringBuilder("");
        *   ch = br.read();
        *  while(讀取的這個字符是換行符的時候){
        *          builder.append(ch);
        *          ch = br.read();
        *  }
        *  return builder.toString();
*
* 3.bw.newLine(); 不同的操作系統,換行符不同
*        (1)在微軟的MS-DOS和Windows中,使用"回車CR('\r')"和"換行LF('\n')"兩個字符作爲換行符;
            Windows系統裏面,每行結尾是 回車+換行(CR+LF),即"\r\n";
       (2)Unix系統裏,每行結尾只有 換行CR,即"\n";
       (3)Mac系統裏,每行結尾是 回車CR 即'\r'。
*  
*  *
* @author Administrator
*
*/
public class TestCopy2 {

       public static void main(String[] args) throws IOException {
               //創建輸入流和輸出流
//                Reader fr = new FileReader(new File("e:/java基礎題目以及答案1.txt"));
//                BufferedReader br = new BufferedReader(fr);
//                Writer fw = new FileWriter(new File("e:/java基礎題目以及答案2.txt"));
//                BufferedWriter bw = new BufferedWriter(fw);
               BufferedReader br = new BufferedReader(new FileReader(new File("e:/java基礎題目以及答案1.txt")));
               BufferedWriter bw = new BufferedWriter(new FileWriter(new File("e:/java基礎題目以及答案2.txt")));
               
               //使用輸入流和輸出流
               //讀一行
               String str = br.readLine();
               while(str != null){
                       //寫一行
                       bw.write(str);
                       bw.newLine();//換一行
                       //讀一行
                       str = br.readLine();
               }                
               
               //關閉輸入流和輸出流                
               br.close();
               bw.close();

       }

}

字符轉換流

何時使用轉換流?

1.    當字節和字符之間有轉換動作時;

2.    流操作的數據需要編碼或解碼時。

 

1).InputStreamReader

InputStreamReader:字節流轉字符流,它使用的字符集可以由名稱指定或顯式給定,否則將接受平臺默認的字符集。

 構造方法:
    // 創建一個使用默認字符集的 InputStreamReader
    InputStreamReader(InputStream in)
    // 創建使用給定字符集的 InputStreamReader
    InputStreamReader(InputStream in, Charset cs)
    // 創建使用給定字符集解碼器的 InputStreamReader
    InputStreamReader(InputStream in, CharsetDecoder dec)
    // 創建使用指定字符集的 InputStreamReader
    InputStreamReader(InputStream in, String charsetName)
 特有方法:
    //返回此流使用的字符編碼的名稱 
    String getEncoding() 
/**
*
*
* 功能:將從鍵盤輸入的一行行數據複製到另外一個文件中
*
* 1.轉換流
*   InputStreamReader  將InputStream轉換成Reader
*   OutputStreamWriter 將OutputStream轉換成Writer
*   ReaderInputStream  這個真沒有
*   WriterOutputStream  這個也沒有
*  
*  
* 2.InputStreamReader到底是個InputStream還是一個Reader
*   Reader reader = new InputStreamReader(is);
*        
*        public class InputStreamReader extends Reader
*
* 3.轉換流使用了一個設計模式:適配器(轉換器)模式
*  
*   手機耳機口(大口)------------(大頭)轉換頭(小口)------ 耳機(小頭)
*
*   Reader(readLine()) ------------   (Reader)轉換流InputStreamReader(InputStream)  ---------  InputStream(System.in)
*  

*
*
*
* @author Administrator
*
*/
public class TestCopy1 {

       public static void main(String[] args) throws IOException {
               //創建輸入流和輸出流
               //Reader reader = new FileReader(new File("e:/java基礎題目以及答案1.txt"));
//                InputStream is = System.in;
//                Reader reader = new InputStreamReader(is);
//                BufferedReader br = new BufferedReader(reader);
               Scanner input = new Scanner(System.in);
               BufferedWriter bw = new BufferedWriter(new FileWriter(new File("e:/java.txt")));
               
               //使用輸入流和輸出流
               //讀一行
       //        String str = br.readLine();
               String str = input.next();
               while(!"bye".equals(str)){ //"null"
                       //寫一行
                       bw.write(str);
                       bw.newLine();//換一行
                       //讀一行
                       //str = br.readLine();
                       str = input.next();
               }                
               
               //關閉輸入流和輸出流                
               //br.close();
               input.close();
               bw.close();

       }

}

 

2).OutputStreamWriter

OutputStreamWriter:字節流轉字符流。

 構造方法:
    // 創建使用默認字符編碼的 OutputStreamWriter
    OutputStreamWriter(OutputStream out)
    // 創建使用給定字符集的 OutputStreamWriter
    OutputStreamWriter(OutputStream out, Charset cs)
    // 創建使用給定字符集編碼器的 OutputStreamWriter
    OutputStreamWriter(OutputStream out, CharsetEncoder enc)
    // 創建使用指定字符集的 OutputStreamWriter
    OutputStreamWriter(OutputStream out, String charsetName)
 特有方法:
    //返回此流使用的字符編碼的名稱 
    String getEncoding() 

(3).FileReader、FileWriter

 FileReader:InputStreamReader類的直接子類,用來讀取字符文件的便捷類,使用默認字符編碼。
 FileWriter:OutputStreamWriter類的直接子類,用來寫入字符文件的便捷類,使用默認字符編碼。

 性能測試和調優

之前說帶緩衝區會快很多,到底是不是這樣呢?

我們複製一個MP4文件來測試一下

不帶緩衝的用例兩秒,這對於一個IO操作來說顯然太長了。

我們用帶緩衝區的試一下:

可以看到,讀取次數一樣,時間少了很多。

但是,讀取次數還是太多了,我們可以通過擴大byte數組的方式來減少讀寫次數。

很明顯,速度進一步加快。

但是請注意:也不是數組越大越好,視情況而定。

我們確定了數組大小之後,我們還可以設置緩衝區的大小進一步優化時間。

因爲我們是從緩衝區讀數據,緩衝區從硬盤讀數據,形成這個體系可以加快我們的速度。

實際中可以多次調整嘗試,確定最優的方案

System類對IO的支持

 針對一些頻繁的設備交互,Java語言系統預定了3個可以直接使用的流對象,分別是:

·        System.in(標準輸入),通常代表鍵盤輸入。

·        System.out(標準輸出):通常寫往顯示器。

·        System.err(標準錯誤輸出):通常寫往顯示器。

PrintStream

/**
*
* System.out 是PrintStream類的一個實例
*                public final static PrintStream out = null;
*                                                    Student  stu  = null;
*
* PrintStream 輸出流  字節流  處理流
*                打印流只有輸出流,沒有輸入流
*
*
* PrintStream類的方法println() 這個方法功能簡直太強大了!!!
*        可以直接講各種數據類型(基本數據類型、引用數據類型)直接寫入到文件中,並且換行。太方便了,太強大了!!
*  不管什麼類型,寫入到文件中全部變成字符串
*  缺點1: 123#3.14#true#bjsxt  需要使用特殊的字符來區分各個內容,防止混淆
*  缺點2: 123#3.14#true======="123"  "3.14"  "true"  讀出來之後都是字符串,還需要將字符串轉換成真實類型
*  
*  DataInputStream和DataOutputStream
*
* @author Administrator
*
*/
public class TestPrintStream {

       public static void main(String[] args) throws FileNotFoundException {
               
               //PrintStream ps = System.out;
               PrintStream ps = new PrintStream(new FileOutputStream(new File("e:/bjsxt.txt")));
               ps.println(123);
               ps.println('A');
               ps.println(3.14);
               ps.println(true);
               ps.println("bjsxt");
               ps.println(new Date().toString());
               
               OutputStream os =new FileOutputStream(new File("e:/bjsxt.txt"));
               
               
//                os.write(一個字節);
//                String datestr = new Date().toString();;
//                byte [] buf = datestr.getBytes();
//                os.write(buf);
//                BufferedWriter bw;
//                bw.newLine();

               ps.close();
       }
       
       public void method1(){
               PrintStream ps = System.out;
               ps.println(123);
               ps.println('A');
               ps.println(3.14);
               ps.println(true);
               ps.println("111");
               ps.println(new Date().toString());
               
//                System.out.println(123);
//                System.out.println('A');
//                System.out.println(3.14);
//                System.out.println(true);
//                System.out.println("111");
//                System.out.println(new Date().toString());
       }

}

PrintWriter

/**
*
* 裝飾模式
*
*   this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
            false);
*
*  減少了子類的數量,是繼承的一種替代方案
*
* @author Administrator
*
*/
public class TestPrintWriter {

       public static void main(String[] args) throws IOException {
               PrintWriter pw1 = new PrintWriter(new FileWriter("e:/bjsxt.txt"));
               
               PrintWriter pw2 = new PrintWriter(new FileOutputStream("e:/bjsxt.txt"));
               
               PrintWriter pw3 = new PrintWriter(new File("e:/bjsxt.txt"));
               
               PrintWriter pw = new PrintWriter("e:/bjsxt.txt");
               pw.println(123);
               pw.println('A');
               pw.println(3.14);
               pw.println(true);
               pw.println("1111t");
               pw.println(new Date().toString());

               
               pw.close();
       }

}

ACM IO 快速讀寫

輸出

第一種使用傳統的System.out.println()方式輸出。

public class Main {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for(int i=0;i<100000;i++)
            System.out.println(i);
        long end = System.currentTimeMillis();
        System.out.println("time="+(end-start)+"ms");
    }
}


time=3443ms
顯然在ACM中會超時

第二種使用PrintWriter輸出:

public class Main {
    public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for(int i=0;i<100000;i++)
            out.println(i);
        out.flush();
        long end = System.currentTimeMillis();
        System.out.println("time="+(end-start)+"ms");
        out.close();
    }
}


結果:
time=328ms

雖然每次輸出的結果會有大致幾十毫秒的偏差,但總體上來看,PrintWriter輸出要比用System.out.println()輸出快上10倍左右。這個結果就比較讓人滿意了。

輸入

Scanner類讀取文件(in.txt,裏面有從一到一百萬的的整數)

public class Main {
    public static void main(String[] args) throws IOException{
        Scanner sc = new Scanner(new FileInputStream("in.txt"));
        long start = System.currentTimeMillis();
        for(int i=1;i<=1000000;i++)
            sc.nextInt();
        long end = System.currentTimeMillis();
        System.out.println("time="+(end-start)+"ms");
    }
}


運行結果:

time=2930ms   
大概3秒,實際上如果ACM中真有一百萬的數據,若用Scanner讀取,還沒開始計算,就已經超時了。

用StreamTokenizer讀取

public class Main {
    public static StreamTokenizer in;
    static {
        try{
            in = new StreamTokenizer(new BufferedReader(new InputStreamReader(new FileInputStream("in.txt"))));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public static int nextInt() throws IOException{ in.nextToken(); return (int)in.nval; }
    public static void main(String[] args) throws IOException{
        long start = System.currentTimeMillis();
        for(int i=1;i<=1000000;i++)
            nextInt();    //這裏僅讀取,不輸出
        long end = System.currentTimeMillis();
        System.out.println("time="+(end-start)+"ms");
    }
}

運行結果:

time=397ms
要注意的是,用StreamTokenizer讀取字符串時,只能讀取純字母字符串,如果包含數字或者其他字符會返回null。這是用StreamTokenizer讀取的缺點。但是用它讀取數字時沒有問題的。

總結一下:
如果數據量比較小,用Scanner是比較方便的
如果數據量很大的話,那麼用StreamTokenizer 是一個很好的選擇

最後是模板:

import java.io.*;

public class Main {
    public static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in),32768));
    public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

    public static double nextDouble() throws IOException{ in.nextToken(); return in.nval; }
    public static float nextFloat() throws IOException{ in.nextToken(); return (float)in.nval; }
    public static int nextInt() throws IOException{ in.nextToken(); return (int)in.nval; }
    public static String next() throws IOException{ in.nextToken(); return in.sval;}

    public static void main(String[] args) throws IOException{
//        獲取輸入
        while(in.nextToken()!=StreamTokenizer.TT_EOF){
            break;
        }
        int x = (int)in.nextToken();  //第一個數據應當通過nextToken()獲取
        
        int y = nextInt();
        float f = nextFloat();
        double d = nextDouble();
        String str = next();

//        輸出
        out.println("abc");
        out.flush();
        out.close();
    }
}

至此,Java的IO總結完啦

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