Java的各種IO操作總結

轉貼來自:http://www.cnblogs.com/wjun530/archive/2007/06/14/782898.html

一. 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 BufferedReader(

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. 輸出到文件

try{

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){

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

}



//5. 數據的存儲和恢復

try{

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 DataInputStream(

new BufferedInputStream(

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

BufferedReader in5br =

new BufferedReader(

new InputStreamReader(in5));

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

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

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

}

catch(EOFException e){

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

}



//6. 通過RandomAccessFile操作文件

RandomAccessFile rf =

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

for(int i=0; i<10; i++)

rf.writeDouble(i*1.414);

rf.close();



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

for(int i=0; i<10; i++)

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

rf.close();



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

rf.seek(5*8);

rf.writeDouble(47.0001);

rf.close();



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

for(int i=0; i<10; i++)

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

rf.close();

}

}

關於代碼的解釋(以區爲單位):

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類對文件進行操作。



----



重要提示:



LineNumberInputStream,StringBufferInputStream已經廢除!大家不要再用!



StringBufferInputStream,This class does not properly convert characters into bytes!



StringBufferInputStream,Deprecated. This class incorrectly assumes that bytes adequately represent characters!





----------------關心IO,就是關心你的JAVA前途之路!-----------------------





DataInputStream流中已經沒有readLine()整個方法!



替換爲: BufferedReader d=new BufferedReader(new InputStreamReader(in));



--------把字節流轉換爲字符流接入緩存讀取字符流中,再進行處理!

這個方法很大的優勢!



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

-----------------Why use character streams?------------------

The primary advantage of character streams is that they make it easy to write programs that are not dependent upon a specific character encoding, and are therefore easy to internationalize. 

Java stores strings in Unicode, an international standard character encoding that is capable of representing most of the world's written languages. Typical user-readable text files, however, use encodings that are not necessarily related to Unicode, or even to ASCII, and there are many such encodings. Character streams hide the complexity of dealing with these encodings by providing two classes that serve as bridges between byte streams and character streams. The InputStreamReader class implements a character-input stream that reads bytes from a byte-input stream and converts them to characters according to a specified encoding. Similarly, the OutputStreamWriter class implements a character-output stream that converts characters into bytes according a specified encoding and writes them to a byte-output stream. 



A second advantage of character streams is that they are potentially much more efficient than byte streams. The implementations of many of Java's original byte streams are oriented around byte-at-a-time read and write operations. The character-stream classes, in contrast, are oriented around buffer-at-a-time read and write operations. This difference, in combination with a more efficient locking scheme, allows the character stream classes to make up for the added overhead of encoding conversion in many cases. 



----------標準設備System.in讀取數據------------------

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

讀取字節:BufferedInputStream

讀取字符:BufferedReader + InputStreamReader

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

import java.io.*;



public class systemin

{

public static void main(String args[])

{ try{ //流轉換!

BufferedReader is=new BufferedReader(new InputStreamReader(System.in))

String inputline=null;

while((inputline=is.readLine())!=null)

System.out.println(inputline);

is.close(); 

}

catch(IOException e)

{ System,out.println("IOXE: "+e);

}

}

} 

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



-----------------標準輸出System.out是一個打印流PrintStream---------------------

import java.io.*;





public class PrintStandardOutput {



public static void main(String[] args) {

String myAnswer = "No, and that's final,";

System.out.println("Hello World of Java");

System.out.println("The answer is " + myAnswer + " at this time."); 



PrintWriter pw = new PrintWriter(System.out);

pw.println("The answer is " + myAnswer + " at this time."); 





int i = 42;

pw.println(i + '=' + " the answer."); 

pw.println("Note: " + i + '=' + " the answer."); 

pw.println(i + "=" + " the answer.");

pw.println(i + ('=' + " the answer.")); 



pw.close(); 

}

}

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

-----------------------要讀取(輸出到—)一個文本文件-----------------------------





BufferedReader is=new BufferedReader(new FileReader("xxxx.text"));讀取

BufferedOutputStream byteout=new BufferedOutputStream(new FileOutputStream("XX.dat"));

// 寫出到文本!



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



---------------利用 BufferedReader--FileReader讀取文本文件!-----------



---------------在IO中始終要注意是字節流還是字符流----------------------

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

import java.io.*;

import java.awt.*;

import javax.swing.*;

import java.awt.event.*;



class filewindow extends JFrame implements ActionListener

{

JTextArea text;

BufferedReader in;

JButton button;

FileReader file;

filewindow()

{

super("文件字符流");

Container con=getContentPane();

text=new JTextArea(50,50);

text.setBackground(Color.blue);

try{

File f=new File("E://a.txt");

file=new FileReader(f);

in=new BufferedReader(file);

/**BufferedReader(Reader in)構造函數,

*文件自字符讀取流FileReader接入BufferedReader

*流中,以便用BufferedReader的對象方法readLine()高效成行讀取!

*/



}

catch(FileNotFoundException e){} 

catch(IOException e){}

button=new JButton("讀取");

button.addActionListener(this);

con.setLayout(new BorderLayout());

setSize(300,200);

setVisible(true);



con.add(text,"Center");

con.add(button,"South");

addWindowListener(new WindowAdapter()

{public void windowClosing(WindowEvent e)

{setVisible(false);System.exit(0);}});



}

public void actionPerformed(ActionEvent e)

{

String s;

if(e.getSource()==button)

try{

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

text.append(s+'/n');

//在這裏大家還可以用BufferString來暫時保存讀取的字符數據!

}

catch(IOException e1){}

}

//---------main()----------

public static void main(String args[])

{

filewindow win=new filewindow();

win.pack();

}

}





-------------------RandomAccessFile隨機讀取文件---------------

import java.io.*;





public class RandomRead

{

final static String FILENAME="E://a.txt";

protected String fileName;

protected RandomAccessFile seeker;



public static void main(String[] argv) throws IOException {

RandomRead r = new RandomRead(FILENAME);



System.out.println("Offset is " + r.readOffset());

System.out.println("Message is /"" + r.readMessage() + "/".");

}



/** Constructor: save filename, construct RandomAccessFile */

public RandomRead(String fname) throws IOException {

fileName = fname;

seeker = new RandomAccessFile(fname, "rw");

}



/** Read the Offset field, defined to be at location 0 in the file. */

public int readOffset() throws IOException {

seeker.seek(0);

seeker.writeChars(FILENAME); // move to very beginning

return seeker.readInt(); // and read the offset

}



/** Read the message at the given offset */

public String readMessage() throws IOException {

seeker.seek(120); // move to where

return seeker.readLine(); // and read the String

}

}



寫得很辛苦,我本來不想再說什麼了,但本着對技術負責的精神還是說出來.



對於I/O的理解屬於3級水平(如果java IO有十級的話)

錯誤太多.

對於I/O層次不熟悉

java IO主要包括

java.io包和java.nio包.



java.io主要從四個接口延伸:

字節:

InputStream/OutputStream,其下爲封裝,過濾,特定對象處理的具體實現類.

字符:

Reader/Writer(原文中連Writer接口全都寫成Write,足以說明根本不瞭解這了接口,如果你經常使用Writer接口怎麼會連Writer和Write都分不清,不是一處失誤,而是全部都是Write)



以上四個接口中,底層全部是操作字節的阻塞方式流.



java.nio主要以塊操作塊(Buffer)爲主,通過可以設定的阻塞和非陰塞模式,極大地提過了數據輸出輸

入的性能,而且將Channel通過選選擇器模式的控制,可以實現在同一輸出輸入通道上多用戶併發進行數據傳輸入.比如一個Socket端口可以同時被無限多(理論上不受限制)個客戶端併發訪問.就是經典的I/O多路複用技術.



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