1. 程式人生 > >深入理解JAVA I/O系列三:字符流詳解

深入理解JAVA I/O系列三:字符流詳解

buffer 情況 二進制文件 感到 復制代碼 使用範圍 轉換 fileread 方式

字符流為何存在

既然字節流提供了能夠處理任何類型的輸入/輸出操作的功能,那為什麽還要存在字符流呢?容我慢慢道來,字節流不能直接操作Unicode字符,因為一個字符有兩個字節,字節流一次只能操作一個字節。如果JAVA不能直接操作字符,我會感到JAVA對這個世界滿滿的惡意,所以提供對直接的字符輸入/輸出的支持是很有必要的,因為我們的口號是:一次編寫,到處運行。

字符流的概念

輸出字符流:把要寫入文件的字符序列(實際是unicode碼元序列)轉為指定編碼方式下的字節序列,然後在寫入文件中。

輸入字符流:把要讀取的字節序列按照指定編碼方式轉為相應的字符序列(實際是unicode碼元序列),從而寫入內存中。

字符流的層次關系

字符流層次結構的頂層是Reader和Writer抽象類,與字節流中的InputStream、OutputStream相對應。

技術分享

技術分享

下面實現這樣一個功能:將字符串寫入一個文件,然後再從文件中讀取在控制臺打印,通過這個DEMO來熟悉字符流家族中的一些常用流。

首先將字符串寫入文件:

技術分享
public static void main(String[] args) throws IOException
    {
        FileOutputStream fis = new FileOutputStream("d:/data.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fis);
        BufferedWriter bw = new BufferedWriter(osw);
        String str1 = "中國移動閱讀基地";
        String str2 = "中國移動視頻基地";
        bw.write(str1);
        bw.write("\r\n");
        bw.write(str2);
        
        bw.close();
    }
技術分享

執行結果:

技術分享

再從文件中讀取打印在控制臺

技術分享
 1         FileOutputStream fos = new FileOutputStream("d:/data.txt");
 2         OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
 3         BufferedWriter bw = new BufferedWriter(osw);
 4         String str1 = "中國移動閱讀基地";
 5         String str2 = "中國移動視頻基地";
 6         bw.write(str1);
 7         bw.write("\r\n");
 8         bw.write(str2);
 9         
10         bw.close();
11         
12         FileInputStream fis = new FileInputStream("d:/data.txt");
13         InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
14         BufferedReader br = new BufferedReader(isr);
15         String str;
16         while(null != (str = br.readLine()))
17         {
18             System.out.println(str);
19         }
20         br.close();
21     
技術分享

執行結果:

中國移動閱讀基地
中國移動視頻基地

1、這裏面的BufferedWriter、BufferedReader與字節流中的BufferedInputStream、BufferedOutputStream相對應,功能原理類似,不做展開介紹。

2、第2行、第13行代碼的作用分別是將字節輸出流、字節輸入流通過制定的編碼方式,轉換成了字符輸出流、字符輸入流。

OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");

OutputStreamWriter、InputStreamReader就是輸入/輸出體系中提供的兩個轉換流,用於實現將字節流轉換成字符流。

大家可以思考這樣一個問題:為什麽沒有把字符流轉換成字節流的轉換流呢?

首先想一字節流和字符流的區別:字節流比字符流的使用範圍更廣,但字符流比字節流操作方便。如果一個流已經是字符流,也就意味著這是一個使用起來更方便的流,為什麽還要轉換成字節流呢?反之,如果現在有一個字節流,但可以確定這個字節流的內容都是文本內容,我們就可以將它轉換成字符流處理起來會更方便一點。所以,java只提供了字節流到字符流的轉換,沒有提供字符流到字節流的轉換。

上面的DEMO是通過字節到字符的轉換流來實現的,下面我們來看看是否可以通過直接讀取文本中的字符來實現:

技術分享
 1 public static void main(String[] args) throws IOException
 2     {
 3         FileWriter fw = new FileWriter("d:data.txt");
 4         BufferedWriter bw = new BufferedWriter(fw);
 5         String str1 = "中國移動閱讀基地";
 6         String str2 = "中國移動視頻基地";
 7         bw.write(str1);
 8         bw.write("\r\n");
 9         bw.write(str2);
10         bw.close();
11         
12         FileReader fr = new FileReader("d:data.txt");
13         BufferedReader br = new BufferedReader(fr);
14         String str;
15         while(null != (str = br.readLine()))
16         {
17             System.out.println(str);
18         }
19         br.close();
20         
21     }
技術分享

執行結果:

中國移動閱讀基地
中國移動視頻基地

我們可以看到,這裏可以通過FileWriter/FileReader來直接操作文本文件。

1、使用FileReader或BufferedReader從文件中讀取字符或文本數據,並總是指定字符編碼;使用FileInputStream從Java中文件或套接字中讀取原始字節流。

2、由於BufferedReader具有一個readLine方法,可以非常方便地一次讀入一行內容,所以經常把讀取文件內容的輸入流包裝成BufferedReader,用來方便地讀取輸入流的文本內容。

知識點TIPS

計算機的文件常被分成文本文件和二進制文件兩大類:

1、我們不妨可以這樣絕對的認為:所有能用記事本打開並且看到其中字符內容文件稱為文本文件,反之則是二進制文件。

2、其實計算機中所有的文件都是二進制文件,文本文只是二進制文件中的一個特殊的存在。如果二進制文件的內容恰好能被正常解析成字符時,則該二進制文件就可以稱之為文本文件。

3、在有些情況下,文本文件使用了錯誤的字符集打開,也會生成亂碼。所以如果向正常使用文本文件,必須在打開文件時使用與保存文件是相同的字符集。

深入理解JAVA I/O系列三:字符流詳解