天天看點

java的new BufferedReader(new InputStreamReader(System.in))

<a target="_blank" href="http://blog.csdn.net/djy1992/article/details/17098467">通過一行常見的代碼讨論:new BufferedReader(new InputStreamReader(System.in))</a>

/*** 

***/

java的IO是基于流(stream)概念的,什麼是流呢,作為初學者,

我是這樣了解的,在各個應用之間傳送的是BITS,這些BIT可已被認為是流體,可以就認為是水流,那麼用來在各個水源之間轉移水的工具應該選擇什麼呢?一般情況下,水管是可以的,是以資料我将資料源比作水源,将流對象比作水管

這樣就有了對流的第一步認識,它再也不神秘了。

對于流,我們要研究些什麼呢,我們主要是針對應用掌握流的特性,而之後根據流的特性,我們轉移不同的資料時,選擇不透的流對象,達到我們的目的。

下面讓我們從一行常見的代碼來分析流吧!

new BufferedReader(new InputStreamReader(System.in)),這是用來從鍵盤接受一行輸入的代碼,下面我們從裡到外進行分析吧。

System.in的類型是InputStream,它代表的是鍵盤接受的輸入,就是說鍵盤是資料源;System.in的類型可以歸結為節點流、位元組流、輸入流;接下來是InputStreamReader這個對象是處理流,字元流,輸入流;

最外面的是BufferedReader的類型是緩沖處理流、字元流、輸入流。是不是有點繞啊,下面我們就從流的分類開始。

流的分類

(重點的通過分類記住這些流的模樣)

  按照方向分類:

     輸入流和輸出流

        流的輸入輸出都是以應用程式為基準的,這一點一定要注意。

        輸入流,模樣很好記,一般情況下,輸入流是帶有Input字樣或Reader字樣的,如FileInputStream和BufferedReader等等,這些都是輸入流。

        輸出流,一般情況下,是帶有Output字樣或Writer的,如FileOutputStream和FileWriter等等,詳細請查查API文檔,看看是不是這樣。

        至于什麼時候使用輸入流,什麼時候使用輸出流,我想我們就不必探讨了吧!

  按照處理的機關:

     位元組流和字元流

        位元組流,一般是帶有Stream字樣的,如InputStream,FileInputStream等等,這組流處理的最小機關之位元組。

        字元流,一般是帶有Reader或Writer字樣的,如InputStreamReader等等,它們處理的最小機關是字元。    

   按照資料的來源:

      節點流和處理流

      節點流的資料來源是應用程式、檔案、鍵盤、等等,是非流對象來源,而處理流的資料來源是其他流對象。

流的使用

一.Input和Output

1.stream代表的是任何有能力産出資料的資料源,或是任何有能力接收資料的接收源。

在Java的IO中,所有的stream(包括Input和Out stream)都包括兩種類型:

1.1 以位元組為導向的stream

以位元組為導向的stream,表示以位元組為機關從stream中讀取或往stream中寫入資訊。以位元組為導向的stream包括下面幾種類型:

1) input stream:

1) ByteArrayInputStream:把記憶體中的一個緩沖區作為InputStream使用

2) StringBufferInputStream:把一個String對象作為InputStream

3) FileInputStream:把一個檔案作為InputStream,實作對檔案的讀取操作

4) PipedInputStream:實作了pipe的概念,主要線上程中使用

5) SequenceInputStream:把多個InputStream合并為一個InputStream

2) Out stream

1) ByteArrayOutputStream:把資訊存入記憶體中的一個緩沖區中

2) FileOutputStream:把資訊存入檔案中

3) PipedOutputStream:實作了pipe的概念,主要線上程中使用

4) SequenceOutputStream:把多個OutStream合并為一個OutStream

1.2 以Unicode字元為導向的stream

以Unicode字元為導向的stream,表示以Unicode字元為機關從stream中讀取或往stream中寫入資訊。以Unicode字元為導向的stream包括下面幾種類型:

1) Input Stream

1) CharArrayReader:與ByteArrayInputStream對應

2) StringReader:與StringBufferInputStream對應

3) FileReader:與FileInputStream對應

4) PipedReader:與PipedInputStream對應

2) Out Stream

1) CharArrayWrite:與ByteArrayOutputStream對應

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

3) FileWrite:與FileOutputStream對應

4) PipedWrite:與PipedOutputStream對應

以字元為導向的stream基本上對有與之相對應的以位元組為導向的stream。兩個對應類實作的功能相同,字是在操作時的導向不同。如CharArrayReader:和ByteArrayInputStream的作用都是把記憶體中的一個緩沖區作為InputStream使用,所不同的是前者每次從記憶體中讀取一個位元組的資訊,而後者每次從記憶體中讀取一個字元。

1.3 兩種不現導向的stream之間的轉換

InputStreamReader和OutputStreamReader:把一個以位元組為導向的stream轉換成一個以字元為導向的stream。

2. stream添加屬性

2.1 “為stream添加屬性”的作用

運用上面介紹的Java中操作IO的API,我們就可完成我們想完成的任何操作了。但通過FilterInputStream和FilterOutStream的子類,我們可以為stream添加屬性。下面以一個

例子來說明這種功能的作用。

如果我們要往一個檔案中寫入資料,我們可以這樣操作:

FileOutStream fs = new FileOutStream(“test.txt”);

然後就可以通過産生的fs對象調用write()函數來往test.txt檔案中寫入資料了。但是,如果我們想實作“先把要寫入檔案的資料先緩存到記憶體中,再把緩存中的資料寫入檔案中”的功能時,上面的API就沒有一個能滿足我們的需求了。但是通過FilterInputStream和FilterOutStream的子類,為FileOutStream添加我們所需要的功能。

2.2 FilterInputStream的各種類型

2.2.1 用于封裝以位元組為導向的InputStream

1) DataInputStream:從stream中讀取基本類型(int、char等)資料。

2) BufferedInputStream:使用緩沖區

3) LineNumberInputStream:會記錄input stream内的行數,然後可以調用getLineNumber()和setLineNumber(int)

4) PushbackInputStream:很少用到,一般用于編譯器開發

2.2.2 用于封裝以字元為導向的InputStream

1) 沒有與DataInputStream對應的類。除非在要使用readLine()時改用BufferedReader,否則使用DataInputStream

2) BufferedReader:與BufferedInputStream對應

3) LineNumberReader:與LineNumberInputStream對應

4) PushBackReader:與PushbackInputStream對應

2.3 FilterOutStream的各種類型

2.2.3 用于封裝以位元組為導向的OutputStream

1) DataIOutStream:往stream中輸出基本類型(int、char等)資料。

2) BufferedOutStream:使用緩沖區

3) PrintStream:産生格式化輸出

2.2.4 用于封裝以字元為導向的OutputStream

1) BufferedWrite:與對應

2) PrintWrite:與對應

3. RandomAccessFile

1) 可通過RandomAccessFile對象完成對檔案的讀寫操作

2) 在産生一個對象時,可指明要打開的檔案的性質:r,隻讀;w,隻寫;rw可讀寫

3) 可以直接跳到檔案中指定的位置

4. I/O應用的一個例子

import java.io.*;

public class TestIO{

public static void main(String[] args)

throws IOException{

//1.以行為機關從一個檔案讀取資料

BufferedReader in = 

new BufferedReader(

new FileReader("F://nepalon//TestIO.java"));

String s, s2 = new String();

while((s = in.readLine()) != null)

s2 += s + "/n";

in.close();

//1b. 接收鍵盤的輸入

BufferedReader stdin = 

new InputStreamReader(System.in));

System.out.println("Enter a line:");

System.out.println(stdin.readLine());

//2. 從一個String對象中讀取資料

StringReader in2 = new StringReader(s2);

int c;

while((c = in2.read()) != -1)

System.out.println((char)c);

in2.close();

//3. 從記憶體取出格式化輸入

try{

DataInputStream in3 = 

new DataInputStream(

new ByteArrayInputStream(s2.getBytes()));

while(true)

System.out.println((char)in3.readByte()); 

}

catch(EOFException e){

System.out.println("End of stream");

//4. 輸出到檔案

BufferedReader in4 = new BufferedReader(new StringReader(s2));

PrintWriter out1 =

new PrintWriter(

new BufferedWriter(

new FileWriter("F://nepalon// TestIO.out")));

int lineCount = 1;

while((s = in4.readLine()) != null)

out1.println(lineCount++ + ":" + s);

out1.close();

in4.close();

catch(EOFException ex){

//5. 資料的存儲和恢複

DataOutputStream out2 = 

new DataOutputStream(

new BufferedOutputStream(

new FileOutputStream("F://nepalon// Data.txt")));

out2.writeDouble(3.1415926);

out2.writeChars("/nThas was pi:writeChars/n");

out2.writeBytes("Thas was pi:writeByte/n");

out2.close();

DataInputStream in5 =

new BufferedInputStream(

new FileInputStream("F://nepalon// Data.txt")));

BufferedReader in5br =

new InputStreamReader(in5));

System.out.println(in5.readDouble());

System.out.println(in5br.readLine());

//6. 通過RandomAccessFile操作檔案

RandomAccessFile rf =

new RandomAccessFile("F://nepalon// rtest.dat", "rw");

for(int i=0; i&lt; 10; i++)

rf.writeDouble(i*1.414);

rf.close();

rf = new RandomAccessFile("F://nepalon// rtest.dat", "r");

System.out.println("Value " + i + ":" + rf.readDouble());

rf = new RandomAccessFile("F://nepalon// rtest.dat", "rw");

rf.seek(5*8);

rf.writeDouble(47.0001);

關于代碼的解釋(以區為機關):

1區中,當讀取檔案時,先把檔案内容讀到緩存中,當調用in.readLine()時,再從緩存中以字元的方式讀取資料(以下簡稱“緩存位元組讀取方式”)。

1b區中,由于想以緩存位元組讀取方式從标準IO(鍵盤)中讀取資料,是以要先把标準IO(System.in)轉換成字元導向的stream,再進行BufferedReader封裝。

2區中,要以字元的形式從一個String對象中讀取資料,是以要産生一個StringReader類型的stream。

4區中,對String對象s2讀取資料時,先把對象中的資料存入緩存中,再從緩沖中進行讀取;對TestIO.out檔案進行操作時,先把格式化後的資訊輸出到緩存中,再把緩存中的資訊輸出到檔案中。

5區中,對Data.txt檔案進行輸出時,是先把基本類型的資料輸出屋緩存中,再把緩存中的資料輸出到檔案中;對檔案進行讀取操作時,先把檔案中的資料讀取到緩存中,再從緩存中以基本類型的形式進行讀取。注意in5.readDouble()這一行。因為寫入第一個writeDouble(),是以為了正确顯示。也要以基本類型的形式進行讀取。

6區是通過RandomAccessFile類對檔案進行操作。