1. 程式人生 > 其它 >Day34---學習Java第二彈

Day34---學習Java第二彈

2021-08-13

Java輸入輸出流

5. FileInputStream流和FileOutputStream的應用

利用程式將檔案file1.txt 拷貝到file2.txt中。
import java.io.File;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.FileInputStream;
 
public class TestFile {
    public static void main(String args[]) throws IOException {
        
try { File inFile = new File("copy.java"); File outFile = new File("copy2.java"); FileInputStream finS = new FileInputStream(inFile); FileOutputStream foutS = new FileOutputStream(outFile); int c; while ((c = finS.read()) != -1) { foutS.write(c); } finS.close(); foutS.close(); }
catch (IOException e) { System.err.println("FileStreamsTest: " + e); } } }

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

計算機訪問外部裝置非常耗時。訪問外存的頻率越高,造成CPU閒置的概率就越大。為了減少訪問外存的次數,

應該在一次對外設的訪問中,讀寫更多的資料。為此,除了程式和流節點間交換資料必需的讀寫機制外,

還應該增加緩衝機制。緩衝流就是每一個數據流分配一個緩衝區,一個緩衝區就是一個臨時儲存資料的記憶體。這樣可以減少訪問硬碟的次數,提高傳輸效率。

BufferedInputStream: BufferedInputStream比FileInputStream多了一個緩衝區。它提供了一個緩衝陣列,

每次呼叫read方法的時候,它首先嚐試從緩衝區裡讀取資料,若讀取失敗(緩衝區無可讀資料),則選擇從物理資料來源

(譬如檔案)讀取新資料(這裡會嘗試儘可能讀取多的位元組)放入到緩衝區中,最後再將緩衝區中的內容部分或全部返回給使用者.

由於從緩衝區裡讀取資料遠比直接從物理資料來源(譬如檔案)讀取速度快。BufferedInputStream的預設緩衝區大小是8192位元組。

當每次讀取的資料量很小時,FileInputStream每次都是從硬碟讀入,而BufferedInputStream大部分是從緩衝區讀入。

讀取記憶體速度比讀取硬碟速度快得多,因此BufferedInputStream效率高。

例如:BUFFER_SIZE < 8192時候,BufferedInputStream效能是很高。

BufferedInputStream bufferedInput = new BufferedInputStream(new FileInputStream(fileA));
byte[] buffer = new byte[BUFFER_SIZE];
int len;
while ((len = bufferedInput.read(buffer)) > 0){
System.out.println(new String(buffer, 0, len));
}
BUFFER_SIZE > 8192時候, FileInputStream和BufferedInputStream兩者效率就沒有明顯差別了。

BufferedOutputStream :執行wirte時先寫入緩衝區,待緩衝區寫滿後,系統再寫入輸出裝置。

1)將檔案讀入記憶體:

將BufferedInputStream與FileInputStream相接

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

BufferedInputStream bin = new BufferedInputStream( in);

2)將記憶體寫入檔案:

將BufferedOutputStream 與 FileOutputStream相接:

String fileB = "/Users/huangguisu/b.txt";
FileOutputStream out = new FileOutputStream(fileB);
BufferedOutputStream bOut = new BufferedOutputStream(out);
byte[] buffer = {0x1,0x2,0x3};
bOut.write(buffer);
bOut.flush();
bOut.close();


3)鍵盤輸入流讀到記憶體
將 BufferedReader 與 標準的資料流 相接
InputStreamReader sin = new InputStreamReader ( System.in) ;
BufferedReader bin = new BufferedReader( sin);

import java.io.*;
 
public class ReadWriteToFile {
    public static void main(String args[]) throws IOException {
        InputStreamReader sin = new InputStreamReader(System.in);
        BufferedReader bin = new BufferedReader(sin);
        FileWriter out = new FileWriter("myfile.txt");
        BufferedWriter bout = new BufferedWriter(out);
        String s;
        while ((s = bin.readLine()).length() > 0) {
            bout.write(s, 0, s.length());
        }
 
    }
}

程式說明:
從鍵盤讀入字元,並寫入到檔案中BufferedReader類的方法:String readLine()
作用:讀一行字串,以回車符為結束。
BufferedWriter類的方法:bout.write(String s,offset,len)
作用:從緩衝區將字串s從offset開始,len長度的字串寫到某處。

八. 字元流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處理的是字元流,在處理字元流時涉及了字元編碼的轉換問題

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

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

Writer類能夠將記憶體中的Unicode字元轉換為其他編碼型別的字元,再寫到輸出流中。

4、BufferedInputStream 和BufferedReader區別
首先雖然都作為一個包裝類,但是BufferedReader針對字元流,BufferedInputStream針對位元組流

BufferedInputStream在實現的時候是在自身read方法中提供快取,是一次取1024或更多位元組然後再慢慢讀,一個個的返回,它並沒有實現讀一行的方法

BufferedReader在實現時通過提供一個readLine方法,使用陣列或者stringBuilder儲存一行資料,並一次性返回


---------------------------------------------------------------------------------------------------------------------------------

下週繼續