天天看點

JAVA 輸入輸出流

Java中把不同的輸入輸出源(鍵盤,檔案,網絡)抽象為流。

流可分為輸入輸出流。

流又分為字元流和位元組流兩大類。

Java輸入流主要是由InputStream和Reader作為基類。輸出流主要是OutputStream和Writer作為基類。

它們都是抽象基類無法建立執行個體。

位元組流主要以InputStream和OutputStream作為基類。而字元流則主要以Reader和Writer作為基類。

可以從一個特定的IO裝置(如鍵盤,網絡)讀寫的流成為位元組流,會和檔案關聯。也稱為低級流(Low Level Stream)。

對一個流進行封裝後的流稱為處理流,也成為進階流。

InputStream 和 Reader分别有一個用于讀取檔案的輸入流:FileInputStream 和 FileReader,它們都是位元組流。

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

InputStream包含的三個方法:

(1)int read()   讀取單個位元組。

(2)int read(byte[] b) 最多讀取b.length的位元組,并将其存儲在數組b中。傳回實際讀取的位元組數。

(3)int read(byte[] b,int of,int len) 此時讀取的起點從off開始。

Reader的三個方法

(1)int read() 讀取單個字元,字元資料可以直接轉換為int類型。

(2)int read(char[] cbuf) 最多讀取cbuf.length個字元

(3)int read(char[] cbuf,int off,int len) 從off位置開始讀。

InputStream和Reader還支援移動記錄指針:

(1)void mark(int readAheadLimit):  在記錄指針目前位置記錄一個标記(mark)

(2)boolean markSupport(): 判斷目前流是否支援記錄标記;

(3)void reset(): 将記錄指針重定位到上一個标記。

(4)long skip(long n): 将記錄指針向前移動n個位元組/字元

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

OutputStream 和 Writer都包含如下三個方法:

(1)void write(int c): 将指定位元組/字元輸出到流中。

(2)void write(byte[]/char[] buf): 将位元組數組/字元數組輸出到流中

(3)void write(byte[]/char[] buf, int off, int len): 将位元組數組/字元數組從off位置開始,長度為len的位元組/字元輸出到流中。

此外,因為字元流以字元為機關,是以Writer還支援用字元串來代替字元數組。包含如下方法:

(1)void write(Strng str): 将字元串包含的字元輸出到流中

(2)void write(Sring str,int off,int len): 将字元串從off位置開始,長度為len的字元輸出到流中。

try {
      /** 擷取檔案輸入流 */
      FileInputStream fis = new FileInputStream(file);

      /** 讀取檔案 */
      while ((length = fis.read(buffer)) > 0) {

        // 需要将字元數組轉化為字元串後輸出,不然輸出的是亂碼,轉成字元串後中文仍是亂碼
        System.out.println("----" + buffer);
        System.out.println("----" + new String(buffer, "utf-8"));
        System.out.println("----" + new String(buffer, 0, length));// offset

      }

    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }      

============================================

上面介紹了輸入輸出流的4個抽象基類,并介紹了4個通路檔案節點流的方法。使用比較繁瑣。

處理流進行輸入輸出更簡單,效率也更高。

通常認為位元組流要比字元流更為強大,因為計算機中是以資料都是二進制的,而位元組流可以處理所有二進制檔案。但轉換成字元就複雜了。是以一般:如果輸入輸出是文本内容則用字元流,如果輸入輸出是二進制,則用位元組流。

四個抽象基類:            InputStream OutputStream Reader Writer

對應四個節點流方法: FileInputStream FileOutputStream FileReader FileWriter

處理流 :                      PrintStream 用來包裝InputStream (包括FileInputStream) 如果需要輸入文本,最好就用處理流。關閉上層的處理流,系統會自動關閉對應的節點流。

轉換流 :                      InputStreamReader : 把位元組流轉換成字元輸入流 InputStreamWriter 把位元組流轉換成字元輸出流

​ 

System.in 代表鍵盤輸入流,但其是Inputstream的執行個體,使用不友善,可以包裝成InputStreamReader 将其轉換為字元輸入流,普通的Reader讀取内容時不友善,可以轉化為BufferReader利用BufferReader的readLine()可以一次讀取一行。

/** 用轉換流就可以不亂碼了。windows使用的gbk,linux平台上中文一般utf-8. 根據tmp.txt的編碼類型來選擇 */
      fis = new FileInputStream(file);
      InputStreamReader reader = new InputStreamReader(fis, "gbk");
      BufferedReader br = new BufferedReader(reader);
      String readStr = null;
      while ((readStr = br.readLine()) != null) {
        System.out.println("-----: " + readStr);
      }      

自動解析編碼:

public String convertCodeAndGetText(String str_filepath) {// 轉碼

        File file = new File(str_filepath);
        BufferedReader reader;
        String text = "";
        try {
                // FileReader f_reader = new FileReader(file);
                // BufferedReader reader = new BufferedReader(f_reader);
                FileInputStream fis = new FileInputStream(file);
                BufferedInputStream in = new BufferedInputStream(fis);
                in.mark(4);
                byte[] first3bytes = new byte[3];
                in.read(first3bytes);//找到文檔的前三個位元組并自動判斷文檔類型。
                in.reset();
                if (first3bytes[0] == (byte) 0xEF && first3bytes[1] == (byte) 0xBB
                                && first3bytes[2] == (byte) 0xBF) {// utf-8

                        reader = new BufferedReader(new InputStreamReader(in, "utf-8"));

                } else if (first3bytes[0] == (byte) 0xFF
                                && first3bytes[1] == (byte) 0xFE) {

                        reader = new BufferedReader(
                                        new InputStreamReader(in, "unicode"));
                } else if (first3bytes[0] == (byte) 0xFE
                                && first3bytes[1] == (byte) 0xFF) {

                        reader = new BufferedReader(new InputStreamReader(in,
                                        "utf-16be"));
                } else if (first3bytes[0] == (byte) 0xFF
                                && first3bytes[1] == (byte) 0xFF) {

                        reader = new BufferedReader(new InputStreamReader(in,
                                        "utf-16le"));
                } else {

                        reader = new BufferedReader(new InputStreamReader(in, "GBK"));
                }
                String str = reader.readLine();

                while (str != null) {
                        text = text + str + "/n";
                        str = reader.readLine();

                }
                reader.close();

        } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
        } catch (IOException e) {
                e.printStackTrace();
        }
        return text;
}