Stream就是信息源与目的地之间的通信路径,这里的信息源可以是文件、内存、网络等。Streams主要分为input及output Stream。
类InputStream处于Input stream类层次的最顶层,它主要具有以下几种方法:
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"); } } } skip方法类似于C语言中的lseek都是用于定位的。Skip方法定义:long skip(long n),该方法使指定流中的当前位置移动n个字节,n的值可以是负值用于向前移,skip方法返回值为实际移动的字节数,由于种种原因,如已到流尾或者其它原因返回的值往往小于n。对于读取文件来说,小于n的原因最大的原因是读到了文件尾。 available方法用于计算指定流中当前有多少字节,如果指定的流是文件流,那么就返回文件的大小。Available返回的值是int类型。 有的输入流可能没有能力返回字节数,如果对这些输入流使用avaiable方法,返回值为0。 对于打开的stream,Java可以自动回收,但是Java自动回收需要时间,所以最好自己调用close方法来关闭stream,这样方便下一次重新指定的流。 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类似,这里不再重复。 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()。 FilterInputStream也是从InputStream中继承下来,不过FilterInputStream类基本上不能直接使用,一般上使用该类的派生类,如BufferedInputStream等。该类的最大特点是,在定义时可以嵌套: InputStream s = getAnInputStreamFromSomewhere(); FilterInputStream s1 = new FilterInputStream(s); FilterInputStream s2 = new FilterInputStream(s1); FilterInputStream s3 = new FilterInputStream(s2); 所以该类的所有派生类都具有这个特性。 BufferedInputStream指定数据源是内存的指定区域,从FilterInputStream继承下来的,这种类型的Stream主要用于提高性能,它定义时一般指定其它的InputStream,如: InputStream s = new BufferedInputStream(new FileInputStream("foo")); BufferedInputSream是可以使用mark及reset方法,使用上述的嵌套方法间接的使其它的stream也支持这些方法了。 由于BufferedInputStream需要buffer,所以它需要等待在它之前的数据都到了后才工作,所以BufferedInputStream最好用在流的前面,如上面这个例子,当然用在最前面也没有什么意思了。 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 ´
´: break loop; case ´
´: int c2 = in.read(); if ((c2 != ´
´) && (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); } 在这个例子中,如果读出的字符中
,还得再读一位判断是否是
,如果不是
,还得将这个字符放回到输入流中,因此使用了PushbackInputStream的功能。 如果对DataInputStream的读操作已到Stream的末尾,会抛出EOFException异常。在Stream末尾,skipBytes不做任何动作;readLine返回null;readUTF抛出UTFDataFormatException异常。 同样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来监控行。从这个子可以看出,嵌套流中数据的流动贯穿所有的流,即所以流中的数据在同步流动。 PushbackInputStream也是从FilterInputStream继承下来,它有一个特殊的方法unread,用于将读出来的数据放出流中。在例子readLine就使用了这个方法,unread与read相对应有三个形态:unread()、unread(byte[])及unread(byte[],int,int)。 FilterInputStream的派生类已介绍完毕,下面接着介绍InputStream的派生类。PipedInputStream一般与PipedOutputStream一起用构成线程之间双向的通信管道。因此在里先不介绍PipedInputStream的用法。 String buffer = "Now is the time for all good men to come..."; InputStream s = new StringBufferInputStream(buffer); ByteArrayInputStream与StringBufferInputStream类似,只是它基于ByteArry,而StringBufferInputStream基于String。 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) ; OutputStream位于Output Stream类层次的最顶层,它是一个抽象类,它规定了Output Stream类的基本功能。 write方法与InputStream的read方法相对应,它有三个形态: (1) write(byte[]):将指定byte数组中的数据输出到指定Stream; (2) write(byte[],int,int):将指定byte数组中的数据从第二个参数开始,输出第三个参数指定的长度到指定的Stream; (3) wirte(int);将一个int值输出到指定的Stream; 有些输出流在输出时先放在缓冲中,可以使用flush将这些数据真正写入指定的输出流中。Close用于关闭指定的输出流。 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数组长度; 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); FilterOutputStream与FilterInputStream相对应,使用方法也相类似。 BufferedOutputStream从FilterOutputStream中继承下来,它与BufferedInputStream相对应,作用也相类似,它主要为输出流做缓冲,如: OutputStream s = new BufferedOutputStream(new FileOutputStream("foo")); 由于BufferedOutputStream是缓冲数据的,所以必要时,需要使用flush方法强制将缓冲中的数据真正写入输出流中。 DataOutputStream与DataInputStream相对应,在继承OutputStream的同时,实现了DataOutput接口,因此它具有DataOutput接中所规定的方法,这些方法与DataInput所规定的方法相反。 它还具有size方法,该方法返回向输出流写入的字节数。以下是实现复制功能的例子: try { while (true) aDO.writeByte(aDI.readByte()); } finally { aDI.close(); aDO.close(); } 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) 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发送过来的数据。再从标准设备中输出。 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的值就不会被输出到输出流。 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.1.2 skip方法
1.1.3 available方法
1.1.4 close方法
1.2 ByteArrayInputStream
1.3 FileInputStream
1.4 FilterInputStream
1.5 BufferedInputStream
1.6 DataInputStream
1.7 LineNumberInputStream
1.8 PushbackInputStream
1.9 PipedInputStream
1.10 StringBufferInputStream
1.11 ByteArrayInputStream
1.12 SequenceInputStream
1.13 OutputStream
1.13.1 write
1.13.2 flush和close
1.14 ByteArrayOutputStream
1.15 FileOutputStream
1.16 FilterOutputStream
1.17 BufferedOutputStream
1.18 DataOutputStream
1.19 PrintStream
1.20 PipedOutputStream
1.21 RandomAccessFile
1.22 StreamTokenizer
1.23 ObjectOutputStream
1.24 ObjectInputStream
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10294527/viewspace-122409/,如需转载,请注明出处,否则将追究法律责任。