admin 管理员组文章数量: 887031
2023年12月19日发(作者:see nested throwable)
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 .*; class TestIO1{ public static void main(String args[]) { InputStream s = null; try{ s = new FileInputStream(""); }catch(FileNotFoundException e){ n("file not find"); } int i; try{ i = (); while(i != -1){ n((char)i); i = (); } }catch(IOException e){ n("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 = (); 这样以后要用到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 = (); int ch2 = (); int ch3 = (); int ch4 = (); 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 = ; int offset = 0; int c; loop: while (true) { switch (c = ()) { case -1: case 'n': break loop; case 'r': int c2 = (); if ((c2 != 'n') && (c2 != -1)) { if (!(in instanceof PushbackInputStream)) { = new PushbackInputStream(in); } ((PushbackInputStream)in).unread(c2); } break loop; default: if (--room < 0) { buf = new char[offset + 128]; room = - offset - 1; opy(lineBuffer, 0, buf, 0, offset); lineBuffer = buf; } buf[offset++] = (char) c; break; } } if ((c == -1) && (offset == 0)) { return null; } return lueOf(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 = ne()) != null) { . . . // process the line n("Did line number: " + eNumber()); } 在这个例子中,使用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 "; 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; ment(s1); ment(s2); ment(s2); e = ts(); 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 = (); 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) yte(te()); } finally { (); (); } 1.19 PrintStream PrintStream是从FilterOutputStream继承下来的。使用例子如下: PrintStream s = new PrintStream(new FileOutputStream("foo")); n("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 .*; class ReadThread extends Thread implements Runnable { InputStream pi = null; OutputStream po = null; String process = null; ReadThread( String process, InputStream pi, OutputStream po) { = pi; = po; s = process; } public void run() { int ch; byte[] buffer = new byte[12]; int bytes_read; try { for(;;) { bytes_read = (buffer); //从指定流读入数据 if (bytes_read == -1) { return; } (buffer, 0, bytes_read);//向指定流写入数据 (); } } catch (Exception e) { tackTrace(); } 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", , readOut ); ReadThread wt = new ReadThread("writer", writeIn, ); (); (); } catch (Exception e) { tackTrace(); } }} 说明: (1) 类ReadThread非常巧妙,它并没有指定输入输出流的具体类型 (2) 在MyPipe类中new ReadThread("reader", , readOut )语句使得从标准输入设备中接收数据,而从readOut输出,而readOut是PipedOutputSteam,所以它可以被另一线程接收; (3) new ReadThread("writer", writeIn, ),从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); bject("Today"); bject(new Date()); (); 可以使用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)ject(); Date date = (Date)ject(); ObjectOutputStream和ObjectInputStream就可以实现对象的持久化,即要先将对象序列化保存到介质中,在必要的时候重新恢复这些对象。 import ; import rmat; /** * 格式化时间类 * = 0 * T = 2 * = 1 * = 2 * = 3 * @author Michael * @version 1.0, 2007/03/09 */ public class Test{ public static void main(String []args){ Date d = new Date(); String s; /** Date类的格式: Sat Apr 16 13:17:29 CST 2006 */ n(d); n("******************************************"); /** getDateInstance() */ /** 输出格式: 2006-4-16 */ s = eInstance().format(d); n(s); /** 输出格式: 2006-4-16 */ s = eInstance(T).format(d); n(s); /** 输出格式: 2006年4月16日 星期六 */ s = eInstance().format(d); n(s); /** 输出格式: 2006-4-16 */ s = eInstance().format(d); n(s); /** 输出格式: 06-4-16 */ s = eInstance().format(d); n(s); /** 输出格式: 2006-01-01 00:00:00 */ rmat format1 = new DateFormat("yyyy-MM-dd hh:mm:ss"); s = (new Date()); n(s); /** 输出格式: 2006-01-01 01:00:00 */ n((new DateFormat("yyyy-MM-dd hh:mm:ss")).format(new Date())); /** 输出格式: 2006-01-01 13:00:00 */ n((new DateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date())); /** 输出格式: 20***/ rmat format2 = new DateFormat("yyyyMMddhhmmss"); s = (new Date()); n(s); } } 补充一下: Calendar cal = tance(); e(new Date()); n("System Date: " + (+1));
版权声明:本文标题:Java Stream全面讲解 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/free/1702952870h437206.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论