流式IO
流(Stream)是字節(jié)的源或目的。
兩種基本的流是:輸入流(Input Stream)和輸出流(Output Stream)??蓮闹凶x出一系列字節(jié)的對象稱為輸入流。而能向其中寫入一系列字節(jié)的對象稱為輸出流。
流的分類
節(jié)點流:從特定的地方讀寫的流類,例如:磁盤或一塊內(nèi)存區(qū)域。 過濾流:使用節(jié)點流作為輸入或輸出。過濾流是使用一個已經(jīng)存在的輸入流或輸出流連接創(chuàng)建的。
InputStream
三個基本的讀方法
abstract int read() :讀取一個字節(jié)數(shù)據(jù),并返回讀到的數(shù)據(jù),如果返回-1,表示讀到了輸入流的末尾。 int read(byte[] b) :將數(shù)據(jù)讀入一個字節(jié)數(shù)組,同時返回實際讀取的字節(jié)數(shù)。如果返回-1,表示讀到了輸入流的末尾。 int read(byte[] b, int off, int len) :將數(shù)據(jù)讀入一個字節(jié)數(shù)組,同時返回實際讀取的字節(jié)數(shù)。如果返回-1,表示讀到了輸入流的末尾。off指定在數(shù)組b中存放數(shù)據(jù)的起始偏移位置;len指定讀取的最大字節(jié)數(shù)。
其它方法 long skip(long n) :在輸入流中跳過n個字節(jié),并返回實際跳過的字節(jié)數(shù)。 int available() :返回在不發(fā)生阻塞的情況下,可讀取的字節(jié)數(shù)。 void close() :關(guān)閉輸入流,釋放和這個流相關(guān)的系統(tǒng)資源。 void mark(int readlimit) :在輸入流的當前位置放置一個標記,如果讀取的字節(jié)數(shù)多于readlimit設置的值,則流忽略這個標記。 void reset() :返回到上一個標記。 boolean markSupported() :測試當前流是否支持mark和reset方法。如果支持,返回true,否則返回false。
OutputStream
三個基本的寫方法 abstract void write(int b) :往輸出流中寫入一個字節(jié)。 void write(byte[] b) :往輸出流中寫入數(shù)組b中的所有字節(jié)。 void write(byte[] b, int off, int len) :往輸出流中寫入數(shù)組b中從偏移量off開始的len個字節(jié)的數(shù)據(jù)。 其它方法 void flush() :刷新輸出流,強制緩沖區(qū)中的輸出字節(jié)被寫出。 void close() :關(guān)閉輸出流,釋放和這個流相關(guān)的系統(tǒng)資源。
------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Demo1:在控制臺讀取鍵盤輸入,然后顯示。Ctrl+C結(jié)束運行 -------------------------------------------------------------------------------
import java.io. * ; public class StreamDemo { public static void main(String[] args) throws Exception { int data; while ((data = System.in.read()) != - 1 ) { System.out.write(data); } } }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
基本的流類
1、FileInputStream和FileOutputStream
節(jié)點流,用于從文件中讀取或往文件中寫入字節(jié)流。如果在構(gòu)造FileOutputStream時,文件已經(jīng)存在,則覆蓋這個文件。
------------------------------------------------------------------------------- Demo2:將字符串寫入特定文件,注意write方法只接收字符數(shù)組。 -------------------------------------------------------------------------------
import java.io. * ; public class StreamDemo { public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream( " 1.txt " ); /**/ /* * 注意:FileOutputStream的write方法接收字符數(shù)組,不能接收String字符串, * 所以要用String的getBytes方法生成一個字符數(shù)組 */ fos.write( " http://www.companysz.com " .getBytes()); fos.close(); } }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
String的構(gòu)造方法的API: ------------ Java API: ------------ String public String(byte[] bytes, int offset, int length)
構(gòu)造一個新的 String,方法是使用指定的字符集解碼字節(jié)的指定子數(shù)組。新的 String 的長度是一個字符集函數(shù),因此不能等于該子數(shù)組的長度。
當給定字節(jié)在給定字符集中無效的情況下,該構(gòu)造方法無指定的行為。當需要進一步控制解碼過程時,應使用 CharsetDecoder 類。
參數(shù): bytes - 要解碼為字符的字節(jié) offset - 要解碼的首字節(jié)的索引 length - 要解碼的字節(jié)數(shù) 拋出: IndexOutOfBoundsException - 如果 offset 和 length 參數(shù)索引字符超出 bytes 數(shù)組的范圍
從以下版本開始: JDK1.1 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Demo3:將字符串寫入特定文件,注意write方法只接收字符數(shù)組。 然后通過文件輸出流讀取數(shù)據(jù),注意使用String特定的構(gòu)造方法。 -------------------------------------------------------------------------------
import java.io. * ; public class StreamDemo { public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream( " 1.txt " ); /**/ /* * 注意:FileOutputStream的write方法接收字符數(shù)組,不能接收String字符串, * 所以要用String的getBytes方法生成一個字符數(shù)組 */ fos.write( " http://www.companysz.com " .getBytes()); fos.close(); // 使用String的這個構(gòu)造方法: // String(byte[] bytes, int offset, int length) FileInputStream fis = new FileInputStream( " 1.txt " ); byte [] buf = new byte [ 100 ]; int len = fis.read(buf); // 使用String的這個構(gòu)造方法: // String(byte[] bytes, int offset, int length) System.out.PRintln( new String(buf, 0 , len)); fis.close(); // 使用完后記得關(guān)閉文件流 } }
------------------------------------------------------------------------------- 運行結(jié)果:
-------------------------------------------------------------------------------
2、BufferedInputStream和BufferedOutputStream
過濾流,需要使用已經(jīng)存在的節(jié)點流來構(gòu)造,提供帶緩沖的讀寫,提高了讀寫的效率。 ------------ Java API: ------------ 構(gòu)造方法摘要 BufferedOutputStream(OutputStream out) 創(chuàng)建一個新的緩沖輸出流,以將數(shù)據(jù)寫入指定的基礎輸出流。 BufferedOutputStream(OutputStream out, int size) 創(chuàng)建一個新的緩沖輸出流,以將具有指定緩沖區(qū)大小的數(shù)據(jù)寫入指定的基礎輸出流。 ------------------------------------------------------------------------------- BufferedOutputStream public BufferedOutputStream(OutputStream out) 創(chuàng)建一個新的緩沖輸出流,以將數(shù)據(jù)寫入指定的基礎輸出流。
參數(shù): out - 基礎輸出流。 BufferedOutputStream public BufferedOutputStream(OutputStream out, int size) 創(chuàng)建一個新的緩沖輸出流,以將具有指定緩沖區(qū)大小的數(shù)據(jù)寫入指定的基礎輸出流。
參數(shù): out - 基礎輸出流。 size - 緩沖區(qū)的大小。 拋出: IllegalArgumentException - 如果 size <= 0 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Demo4:通過一個OutputStream對象來構(gòu)造一個BufferedOutputStream對象。 而FileOutputStream類是OutputStream類的子類,所以可以用它來構(gòu)造。 -------------------------------------------------------------------------------
import java.io. * ; public class StreamDemo { public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream( " 1.txt " ); BufferedOutputStream bos = new BufferedOutputStream(fos); bos.write( " http://www.companysz.com " .getBytes()); } }
------------------------------------------------------------------------------- 運行結(jié)果:1.txt文件為空。原因:緩沖區(qū)沒有寫滿,程序沒有向文件寫數(shù)據(jù)。 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- 解決方法1:使用flush()方法: ------------------------------------------------------------------------------- Demo4:使用flush()方法,可以使程序立即向文件寫數(shù)據(jù)。 -------------------------------------------------------------------------------
import java.io. * ; public class StreamDemo { public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream( " 1.txt " ); BufferedOutputStream bos = new BufferedOutputStream(fos); bos.write( " http://www.companysz.com " .getBytes()); bos.flush(); } }
------------------------------------------------------------------------------- 運行結(jié)果:數(shù)據(jù)被寫入相應的文件。 ------------------------------------------------------------------------------- 解決方法2:使用close()方法: ------------------------------------------------------------------------------- Demo5:使用close()方法,同樣可以使程序立即向文件寫數(shù)據(jù)。 -------------------------------------------------------------------------------
import java.io. * ; public class StreamDemo { public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream( " 1.txt " ); BufferedOutputStream bos = new BufferedOutputStream(fos); bos.write( " http://www.companysz.com " .getBytes()); bos.close(); } }
------------------------------------------------------------------------------- 運行結(jié)果:數(shù)據(jù)被寫入相應的文件。 -------------------------------------------------------------------------------
flush()和close()的區(qū)別: 還要使用流對象,還需要寫數(shù)據(jù),使用flush(),否則使用close()。
另外,使用close()將關(guān)閉自己的流對象,同時會關(guān)閉與之相關(guān)的流對象,如FileOutputStream流。
------------------------------------------------------------------------------- Demo6:使用BufferedInputStream流,從文件中讀取數(shù)據(jù)。 同樣要用InputStream流對象或者其子類的對象來構(gòu)造。 -------------------------------------------------------------------------------
import java.io. * ; public class StreamDemo { public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream( " 1.txt " ); BufferedOutputStream bos = new BufferedOutputStream(fos); bos.write( " http://www.companysz.com " .getBytes()); bos.close(); FileInputStream fis = new FileInputStream( " 1.txt " ); BufferedInputStream bis = new BufferedInputStream(fis); byte [] buf = new byte [ 100 ]; int len = bis.read(buf); // 使用String的這個構(gòu)造方法: // String(byte[] bytes, int offset, int length) System.out.println( new String(buf, 0 , len)); bis.close(); } }
------------------------------------------------------------------------------- 運行結(jié)果: -------------------------------------------------------------------------------
3、DataInputStream和DataOutputStream
過濾流,需要使用已經(jīng)存在的節(jié)點流來構(gòu)造,提供了讀寫Java中的基本數(shù)據(jù)類型的功能。 ------------ Java API: ------------ java.io 類 DataOutputStream java.lang.Object java.io.OutputStream java.io.FilterOutputStream java.io.DataOutputStream 所有已實現(xiàn)的接口: Closeable, DataOutput, Flushable public class DataOutputStream extends FilterOutputStream implements DataOutput
數(shù)據(jù)輸出流允許應用程序以適當方式將基本 Java 數(shù)據(jù)類型寫入輸出流中。然后,應用程序可以使用數(shù)據(jù)輸入流將數(shù)據(jù)讀入。
從以下版本開始: JDK1.0 ------------------------------------------------------------------------------- 構(gòu)造方法摘要 DataOutputStream(OutputStream out) 創(chuàng)建一個新的數(shù)據(jù)輸出流,將數(shù)據(jù)寫入指定基礎輸出流。 ------------------------------------------------------------------------------- DataOutputStream public DataOutputStream(OutputStream out) 創(chuàng)建一個新的數(shù)據(jù)輸出流,將數(shù)據(jù)寫入指定基礎輸出流。計數(shù)器 written 被設置為零。
參數(shù): out - 基礎輸出流,將被保存供以后使用。 ------------------------------------------------------------------------------- Demo7:使用DataOutputStream流,將基本數(shù)據(jù)類型以二進制形式寫入文件中。 同樣要用InputStream流對象或者其子類的對象來構(gòu)造, 這里使用BufferedOutputStream對象來構(gòu)造。 -------------------------------------------------------------------------------
import java.io. * ; public class StreamDemo { public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream( " dos.txt " ); // 獲得寫入文件功能 BufferedOutputStream bos = new BufferedOutputStream(fos); // 獲得緩沖功能 DataOutputStream dos = new DataOutputStream(bos); // 獲得寫入基本類型功能 /* * 定義8種基本類型的對象 */ byte b = 3 ; short s = 4 ; int i = 78 ; long l = 100000 ; char ch = ' a ' ; boolean bl = false ; float f = 4.5f ; double d = 4.0001 ; /* * 將8種基本類型的對象寫入文件中 */ dos.writeByte(b); dos.writeShort(s); dos.writeInt(i); dos.writeLong(l); dos.writeChar(ch); dos.writeBoolean(bl); dos.writeFloat(f); dos.writeDouble(d); dos.close(); } }
------------------------------------------------------------------------------- 運行結(jié)果:8種基本類型的數(shù)據(jù)以二進制形式寫入指定的文件中。 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Demo8:從指定的文件中讀取8種基本類型的數(shù)據(jù) -------------------------------------------------------------------------------
import java.io. * ; public class StreamDemo { public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream( " dos.txt " ); // 獲得寫入文件功能 BufferedOutputStream bos = new BufferedOutputStream(fos); // 獲得緩沖功能 DataOutputStream dos = new DataOutputStream(bos); // 獲得寫入基本類型功能 /* * 定義8種基本類型的對象 */ byte b = 3 ; short s = 4 ; int i = 78 ; long l = 100000 ; char ch = ' a ' ; boolean bl = false ; float f = 4.5f ; double d = 4.0001 ; /* * 將8種基本類型的對象寫入文件中 */ dos.writeByte(b); dos.writeShort(s); dos.writeInt(i); dos.writeLong(l); dos.writeChar(ch); dos.writeBoolean(bl); dos.writeFloat(f); dos.writeDouble(d); dos.close(); FileInputStream fis = new FileInputStream( " dos.txt " ); BufferedInputStream bis = new BufferedInputStream(fis); DataInputStream dis = new DataInputStream(bis); System.out.println(dis.readByte()); System.out.println(dis.readShort()); System.out.println(dis.readInt()); System.out.println(dis.readLong()); System.out.println(dis.readChar()); System.out.println(dis.readBoolean()); System.out.println(dis.readFloat()); System.out.println(dis.readDouble()); dis.close(); } }
------------------------------------------------------------------------------- 運行結(jié)果:數(shù)據(jù)正常輸出: 3 4 78 100000 a false 4.5 4.0001 -------------------------------------------------------------------------------
4、PipedInputStream和PipedOutputStream
管道流,用于線程間的通信。一個線程的PipedInputStream對象從另一個線程的PipedOutputStream對象讀取輸入。要使管道流有用,必須同時構(gòu)造管道輸入流和管道輸出流。 ------------------------------------------------------------------------------- ------------ Java API: ------------ java.io 類 PipedInputStream java.lang.Object java.io.InputStream java.io.PipedInputStream 所有已實現(xiàn)的接口: Closeable public class PipedInputStream extends InputStream
傳送輸入流應該連接到傳送輸出流;傳送輸入流會提供要寫入傳送輸出流的所有數(shù)據(jù)字節(jié)。通常,數(shù)據(jù)由某個線程從 PipedInputStream 對象讀取,并由其他線程將其寫入到相應的 PipedOutputStream。不建議對這兩個對象嘗試使用單個線程,因為這樣可能會死鎖該線程。傳送輸入流包含一個緩沖區(qū),可在緩沖區(qū)限定的范圍內(nèi)將讀操作和寫操作分離開。 從以下版本開始: JDK1.0 ------------------------------------------------------------------------------- ------------ Java API: ------------ java.io 類 PipedOutputStream java.lang.Object java.io.OutputStream java.io.PipedOutputStream 所有已實現(xiàn)的接口: Closeable, Flushable public class PipedOutputStream extends OutputStream
傳送輸出流可以連接到傳送輸入流,以創(chuàng)建通信管道。傳送輸出流是管道的發(fā)送端。通常,數(shù)據(jù)由某個線程寫入 PipedOutputStream 對象,并由其他線程從連接的 PipedInputStream 讀取。不建議對這兩個對象嘗試使用單個線程,因為這樣可能會死鎖該線程。
從以下版本開始: JDK1.0 ------------------------------------------------------------------------------- ------------ Java API: ------------ connect public void connect(PipedInputStream snk) throws IOException 將此傳送輸出流連接到接收者。如果此對象已經(jīng)連接到其他某個傳送輸入流,則拋出 IOException。
如果 snk 為未連接的傳送輸入流,而 src 為未連接的傳送輸出流,則可以通過以下任一調(diào)用使其連接: src.connect(snk) 或: snk.connect(src) 這兩個調(diào)用的效果相同。
參數(shù): snk - 要連接的傳送輸入流。 拋出: IOException - 如果發(fā)生 I/O 錯誤。 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Demo9:利用管道輸入流和輸出流進行通訊。 -------------------------------------------------------------------------------
import java.io. * ; public class PipedStreamDemo { public static void main(String[] args) { PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(); try { pos.connect(pis); // pis.connect(pos); 二選一即可 new Producer(pos).start(); new Consumer(pis).start(); } catch (IOException e) { // TODO 自動生成 catch 塊 e.printStackTrace(); } } } /* * 生產(chǎn)者線程 */ class Producer extends Thread { private PipedOutputStream pos; public Producer(PipedOutputStream pos) { this .pos = pos; } public void run() { try { pos.write( " Hello, welcome you! " .getBytes()); pos.close(); } catch (Exception e) { e.printStackTrace(); } } } /* * 消費者線程 */ class Consumer extends Thread { private PipedInputStream pis; public Consumer(PipedInputStream pis) { this .pis = pis; } public void run() { try { byte [] buf = new byte [ 100 ]; int len = pis.read(buf); System.out.println( new String(buf, 0 , len)); pis.close(); // 關(guān)閉輸入流 } catch (Exception e) { e.printStackTrace(); } } }
------------------------------------------------------------------------------- 運行結(jié)果:輸出Hello, welcome you! -------------------------------------------------------------------------------
轉(zhuǎn)自:http://www.blogjava.net/coderdream/articles/65609.html
新聞熱點
疑難解答