程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java入門筆記7_Stream

Java入門筆記7_Stream

編輯:關於JAVA

1. Streams及I/O

Stream就是信息源與目的地之間的通信路徑,這裡的信息源可以是文件、內存、網絡等。Streams主要分為input及output Stream。

1.1 InputStream類

類InputStream處於Input stream類層次的最頂層,它主要具有以下幾種方法:

1.1.1 read方法

read方法用於從指定的輸入流讀取以字節為單位的數據,第一次從流的開始位置開始讀取,以後每次從上次的結束部位開始讀取,即自動實現了位移。

read方法有以下三種形態:

(1) int read(byte buff[n]):從指定輸入流中讀取n個字節填充到buff中,該方法返回讀取的實際字節數,如果讀取的實際字節數小於n,一般是因為已讀到指定輸入流的末尾;

(2) int read():即不帶參數,該方法每次一個字節從指定的輸入流中讀取數據。返回值也是int類型,但它並不代表讀取的字節數,而是從流中讀取的數據的本身,因數據本身是byte類型的,所以一般要強制進行轉化;如果讀到流的末尾返回的值是-1;

(3) int read(byte buff[n],int start, int len):從指定流讀取數據,從start開始,填充len個字節到buff中,返回值為實際的填充數,如果返回值

以下是read的簡單例子:

import Java.io.*;

class TestIO1{

public static void main(String args[]) {

InputStream s = null;

try{

s = new FileInputStream("io.txt");

}catch(FileNotFoundException e){

System.out.println("file not find");

}

int i;

try{

i = s.read();

while(i != -1){

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

i = s.read();

}

}catch(IOException e){

System.out.println("io error");

} } }

1.1.2 skip方法

skip方法類似於C語言中的lseek都是用於定位的。Skip方法定義:long skip(long n),該方法使指定流中的當前位置移動n個字節,n的值可以是負值用於向前移,skip方法返回值為實際移動的字節數,由於種種原因,如已到流尾或者其它原因返回的值往往小於n。對於讀取文件來說,小於n的原因最大的原因是讀到了文件尾。

1.1.3 available方法

available方法用於計算指定流中當前有多少字節,如果指定的流是文件流,那麼就返回文件的大小。Available返回的值是int類型。

有的輸入流可能沒有能力返回字節數,如果對這些輸入流使用avaiable方法,返回值為0。

1.1.4 close方法

對於打開的stream,Java可以自動回收,但是Java自動回收需要時間,所以最好自己調用close方法來關閉stream,這樣方便下一次重新指定的流。

1.2 ByteArrayInputStream

ByteArrayInputStream是從InputStream中繼承下來的,用於從字節數組中提取數據,關於ByteArrayInputStream的創建例子如下:

byte[] buffer = new byte[1024];

fillWithUsefulData(buffer); //自定義的方法,用於在buffer中填充數據

InputStream s = new ByteArrayInputStream(buffer);

InputStream s1 = new ByteArrayInputStream(buffer,100,300);

其中ByteArrayInputStream(buffer,100,300)是創建到buffer的stream,從buffer的第100個字節開始取300字節。

ByteArrayInputStream的其它方法與InputStream類似,這裡不再重復。

1.3 FileInputStream

FileInputStream也是從InputStream中繼承下來的,用於從指定的文件中提取。因此它的方法也與InputStream中的方法類似,這裡不再介紹,只介紹FileInputStream中特殊的方法:getFD(),該方法用於獲取文件句柄。使用方法如下:

FileInputStream aFIS = new FileInputStream("aFileName");

FileDescriptor myFD = aFIS.getFD();

這樣以後要用到aFileName文件時可以使用myFD這個文件句柄(實際上是文件描述類的實例),如要重新打開該文件,可以使用FileInputStream aFIS = new FileInputStream(myFD)。

關於文件描述類FileDescriptor,有以下幾點說明:

(1) 屬性in:標准輸入;

(2) 屬性out:標准輸出;

(3) 屬性err:標准錯誤輸出;

在FileInputStream中還有另一個特殊的方法就是:finalize()。

1.4 FilterInputStream

FilterInputStream也是從InputStream中繼承下來,不過FilterInputStream類基本上不能直接使用,一般上使用該類的派生類,如BufferedInputStream等。該類的最大特點是,在定義時可以嵌套:

InputStream s = getAnInputStreamFromSomewhere();

FilterInputStream s1 = new FilterInputStream(s);

FilterInputStream s2 = new FilterInputStream(s1);

FilterInputStream s3 = new FilterInputStream(s2);

所以該類的所有派生類都具有這個特性。

1.5 BufferedInputStream

BufferedInputStream指定數據源是內存的指定區域,從FilterInputStream繼承下來的,這種類型的Stream主要用於提高性能,它定義時一般指定其它的InputStream,如:

InputStream s = new BufferedInputStream(new FileInputStream("foo"));

BufferedInputSream是可以使用mark及reset方法,使用上述的嵌套方法間接的使其它的stream也支持這些方法了。

由於BufferedInputStream需要buffer,所以它需要等待在它之前的數據都到了後才工作,所以BufferedInputStream最好用在流的前面,如上面這個例子,當然用在最前面也沒有什麼意思了。

1.6 DataInputStream

DataInputStream也是從FilterInputStream繼承下來的,所以也具有父類的特性。DataInputStream還implement DataInput接口,所以DataInputStream具體的方法最多,如:readShort、readBoolean、readByte、readUnsignedByte、readShort等。這些方法的都是read方法的擴展,使用上也相似,所以這裡不多介紹。

以下是readInt的實現:

public final int readInt() throws IOException {

int ch1 = in.read();

int ch2 = in.read();

int ch3 = in.read();

int ch4 = in.read();

if ((ch1 | ch2 | ch3 | ch4) < 0)

throw new EOFException();

return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));

}

以下是readLine的實現:

public final String readLine() throws IOException {

char buf[] = lineBuffer;

if (buf == null) {

buf = lineBuffer = new char[128];

}

int room = buf.length;

int offset = 0;

int c;

loop: while (true) {

switch (c = in.read()) {

case -1:

case '\n':

break loop;

case '\r':

int c2 = in.read();

if ((c2 != '\n') && (c2 != -1)) {

if (!(in instanceof PushbackInputStream)) {

this.in = new PushbackInputStream(in);

}

((PushbackInputStream)in).unread(c2);

}

break loop;

default:

if (--room < 0) {

buf = new char[offset + 128];

room = buf.length - offset - 1;

System.arraycopy(lineBuffer, 0, buf, 0, offset);

lineBuffer = buf;

}

buf[offset++] = (char) c;

break;

}

}

if ((c == -1) && (offset == 0)) {

return null;

}

return String.copyValueOf(buf, 0, offset);

}

在這個例子中,如果讀出的字符中\r,還得再讀一位判斷是否是\n,如果不是\n,還得將這個字符放回到輸入流中,因此使用了PushbackInputStream的功能。

如果對DataInputStream的讀操作已到Stream的末尾,會拋出EOFException異常。在Stream末尾,skipBytes不做任何動作;readLine返回null;readUTF拋出UTFDataFormatException異常。

1.7 LineNumberInputStream

同樣LineNumberInputStream是從FilterInputStream繼承下來的,該類可以跟蹤行號,設置行號,對行作標記以便恢復等功能。一般不直接使用該類,而使用其它Stream的嵌套間接對它進行使用,如:

LineNumberInputStream aLNIS;

aLNIS = new LineNumberInputStream(new FileInputStream("source"));

DataInputStream s = new DataInputStream(aLNIS);

String line;

while ((line = s.readLine()) != null) {

. . . // process the line

System.out.println("Did line number: " + aLNIS.getLineNumber());

}

在這個例子中,使用DataInputStream讀取行,使用LineNumberInputStream來監控行。從這個子可以看出,嵌套流中數據的流動貫穿所有的流,即所以流中的數據在同步流動。

1.8 PushbackInputStream

PushbackInputStream也是從FilterInputStream繼承下來,它有一個特殊的方法unread,用於將讀出來的數據放出流中。在例子readLine就使用了這個方法,unread與read相對應有三個形態:unread()、unread(byte[])及unread(byte[],int,int)。

1.9 PipedInputStream

FilterInputStream的派生類已介紹完畢,下面接著介紹InputStream的派生類。PipedInputStream一般與PipedOutputStream一起用構成線程之間雙向的通信管道。因此在裡先不介紹PipedInputStream的用法。

1.10 StringBufferInputStream

String buffer = "Now is the time for all good men to come...";

InputStream s = new StringBufferInputStream(buffer);

1.11 ByteArrayInputStream

ByteArrayInputStream與StringBufferInputStream類似,只是它基於ByteArry,而StringBufferInputStream基於String。

1.12 SequenceInputStream

SequenceInputStream用於將不同的InputStream按先後順序串在一起,如將兩個InputStream串起來:

InputStream s1 = new FileInputStream("theFirstPart");

InputStream s2 = new FileInputStream("theRest");

InputStream s = new SequenceInputStream(s1, s2);

以上只能實現兩個輸入流的串接,要實現兩個以上輸入流串接,需要用到Vector類,如下所示:

Vector v = new Vector(3);

Enumeration e;

v.addElement(s1);

v.addElement(s2);

v.addElement(s2);

e = v.elements();

InputStream s = new SequenceInputStream(e) ;

1.13 OutputStream

OutputStream位於Output Stream類層次的最頂層,它是一個抽象類,它規定了Output Stream類的基本功能。

1.13.1 write

write方法與InputStream的read方法相對應,它有三個形態:

(1) write(byte[]):將指定byte數組中的數據輸出到指定Stream;

(2) write(byte[],int,int):將指定byte數組中的數據從第二個參數開始,輸出第三個參數指定的長度到指定的Stream;

(3) wirte(int);將一個int值輸出到指定的Stream;

1.13.2 flush和close

有些輸出流在輸出時先放在緩沖中,可以使用flush將這些數據真正寫入指定的輸出流中。Close用於關閉指定的輸出流。

1.14 ByteArrayOutputStream

ByteArrayOutputStream將一個輸出流指向一個Byte數組,但這個Byte數組是ByteArrayOutputStream內部內置的,不需要我們來定義。該類有兩個構造函數:

(1) ByteArrayOutputStream():該構造函數會在內部創建一個長度為32的Byte數組;

(2) ByteArrayOutputStream(int n):在對象內部創建一個長度為n的Byte數組。

ByteArrayOutputStream從OutputStream類繼承下來,所以它具write、flush及close等方法,同時它還具有以下幾個特殊的方法:

(3) toString():將對象內部的Byte數組轉化成字符串(String(buf,0,count);

(4) toString(int n):將對象對部的Byte數組轉化成字符串,編碼方式為n;

(5) toString(String n):將對象對部的數組轉化成字符串,編碼方式為n;

(6) toByteArray():返回對象內部的Byte數組;

(7) writeTo(OutputStream):將內部Byte數組輸出到指定的輸出流;

(8) reset():將對象內部Byte數組的長度設為0,{count = 0};

(9) size():返回Byte數組長度;

1.15 FileOutputStream

FileOutputStream與FileInputStream相對應,它具有以下幾個構造函數:

(1) FileOutputStream(File)

(2) FileOutputStream(File file, boolean append):如果append為真,以添加方式寫入文件,如果為否(缺省),以新增方式寫入文件;

(3) FileOutputStream(FileDescriptor)

(4) FileOutputStream(String name)

(5) FileOutputStream(String name, boolean append)

其它的方法大多為標准方法,這裡不再介紹。以下使用的例子:

FileDescriptor fd = someFileStream.getFD();

OutputStream s = new FileOutputStream(fd);

1.16 FilterOutputStream

FilterOutputStream與FilterInputStream相對應,使用方法也相類似。

1.17 BufferedOutputStream

BufferedOutputStream從FilterOutputStream中繼承下來,它與BufferedInputStream相對應,作用也相類似,它主要為輸出流做緩沖,如:

OutputStream s = new BufferedOutputStream(new FileOutputStream("foo"));

由於BufferedOutputStream是緩沖數據的,所以必要時,需要使用flush方法強制將緩沖中的數據真正寫入輸出流中。

1.18 DataOutputStream

DataOutputStream與DataInputStream相對應,在繼承OutputStream的同時,實現了DataOutput接口,因此它具有DataOutput接中所規定的方法,這些方法與DataInput所規定的方法相反。

它還具有size方法,該方法返回向輸出流寫入的字節數。以下是實現復制功能的例子:

try { while (true) aDO.writeByte(aDI.readByte()); }

finally { aDI.close(); aDO.close(); }

1.19 PrintStream

PrintStream是從FilterOutputStream繼承下來的。使用例子如下:

PrintStream s = new PrintStream(new FileOutputStream("foo"));

s.println("Here's the first line of text in the file foo.");

這個例子說明可以使用PrintStream向文件寫數據,並且該類提供了輸出行的功能,彌補了DataOutputStream的空白(在DataOutputStream沒有輸出行的功能)。

PrintStream的構造函數:

(1) PrintStream(boolean autoFlush, OutputStream out)

(2) PrintStream(OutputStream out)

(3) PrintStream(OutputStream out, boolean autoFlush)

(4) PrintStream(OutputStream out, boolean autoFlush, String encoding)

1.20 PipedOutputStream

PipedOutputStream與PipedInputSteam相互配合實現兩個線程之間的通信,它們的定義如下:

PipedInputStream sIn = PipedInputStream();

PipedOutputStream sOut = PipedOutputStream(sIn);

以下是使用例子,該例子接收標准輸入的數據,並輸出到標准輸出:

import Java.io.*;

class ReadThread extends Thread implements Runnable {

InputStream pi = null;

OutputStream po = null;

String process = null;

ReadThread( String process, InputStream pi, OutputStream po) {

this.pi = pi; this.po = po; this.process = process; }

public void run() {

int ch; byte[] buffer = new byte[12]; int bytes_read;

try {

for(;;) {

bytes_read = pi.read(buffer); //從指定流讀入數據

if (bytes_read == -1) { return; }

po.write(buffer, 0, bytes_read);//向指定流寫入數據

Thread.yIEld();

}

} catch (Exception e) { e.printStackTrace();

} finally { }

}

}

public class MyPipe{

public static void main( String [] args) {

try {

int ch;

PipedInputStream writeIn = new PipedInputStream();

PipedOutputStream readOut = new PipedOutputStream( writeIn );

FileOutputStream writeOut = new FileOutputStream("out");

ReadThread rt = new ReadThread("reader", System.in, readOut );

ReadThread wt = new ReadThread("writer", writeIn, System.out );

rt.start();

wt.start();

} catch (Exception e) {

e.printStackTrace();

} }}

說明:

(1) 類ReadThread非常巧妙,它並沒有指定輸入輸出流的具體類型

(2) 在MyPipe類中new ReadThread("reader", System.in, readOut )語句使得從標准輸入設備中接收數據,而從readOut輸出,而readOut是PipedOutputSteam,所以它可以被另一線程接收;

(3) new ReadThread("writer", writeIn, System.out ),從writeIn接收數據,writeIn是readOut是成對的雙向管道,它接收從readOut發送過來的數據。再從標准設備中輸出。

1.21 RandomAccessFile

1.22 StreamTokenizer

1.23 ObjectOutputStream

ObjectOutputStream從OutputStream繼承下來,並實現了ObjectOutput, ObjectStreamConstants這兩個接口。它負責將指定對象輸出到指定的輸出流,可以將非static、非transIEnt的屬性及值,對象的類定義輸出到指定的輸出流。該類有一個非常用的方法:

writeObject (Object obj);

該方法將obj輸出到指定的輸出流,以下是該類的例子:

FileOutputStream f = new FileOutputStream("tmp");

ObjectOutput s = new ObjectOutputStream(f);

s.writeObject("Today");

s.writeObject(new Date());

s.flush();

可以使用transIEnt修飾符規定一些變量的值不被輸出到指定的輸出流,如:

public transient int transIEntValue = 4;

這樣transIEntValue的值就不會被輸出到輸出流。

1.24 ObjectInputStream

ObjectInputStream與ObjectOutputStream相對應,它是將對象的值及類的定義等從指定的輸入流讀入,以便重新對象化:

FileInputStream in = new FileInputStream("tmp");

ObjectInputStream s = new ObjectInputStream(in);

String today = (String)s.readObject();

Date date = (Date)s.readObject();

ObjectOutputStream和ObjectInputStream就可以實現對象的持久化,即要先將對象序列化保存到介質中,在必要的時候重新恢復這些對象。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved