中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Java > 综合文章
Java入门笔记7_Stream
作者:佚名 时间:2006-09-16 08:48 出处:月光软件站 责编:月夜寒箫
              摘要:Java入门笔记7_Stream

1. StreamsI/O

 

 

Stream就是信息源与目的地之间的通信路径,这里的信息源可以是文件、内存、网络等。Streams主要分为inputoutput 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中,返回值为实际的填充数,如果返回值<len,一般表示已将指定流中的数据读完;

 

以下是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方法

 

对于打开的streamJava可以自动回收,但是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)是创建到bufferstream,从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是可以使用markreset方法,使用上述的嵌套方法间接的使其它的stream也支持这些方法了。

 

由于BufferedInputStream需要buffer,所以它需要等待在它之前的数据都到了后才工作,所以BufferedInputStream最好用在流的前面,如上面这个例子,当然用在最前面也没有什么意思了。

 

1.6 DataInputStream

 

 

DataInputStream也是从FilterInputStream继承下来的,所以也具有父类的特性。DataInputStreamimplement DataInput接口,所以DataInputStream具体的方法最多,如:readShortreadBooleanreadBytereadUnsignedBytereadShort等。这些方法的都是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返回nullreadUTF抛出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就使用了这个方法,unreadread相对应有三个形态: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

 

ByteArrayInputStreamStringBufferInputStream类似,只是它基于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方法与InputStreamread方法相对应,它有三个形态:

 

(1) write(byte[]):将指定byte数组中的数据输出到指定Stream

 

(2) write(byte[],int,int):将指定byte数组中的数据从第二个参数开始,输出第三个参数指定的长度到指定的Stream

 

(3) wirte(int);将一个int值输出到指定的Stream

 

1.13.2 flushclose

 

有些输出流在输出时先放在缓冲中,可以使用flush将这些数据真正写入指定的输出流中。Close用于关闭指定的输出流。

 

1.14 ByteArrayOutputStream

 

ByteArrayOutputStream将一个输出流指向一个Byte数组,但这个Byte数组是ByteArrayOutputStream内部内置的,不需要我们来定义。该类有两个构造函数:

 

(1) ByteArrayOutputStream():该构造函数会在内部创建一个长度为32Byte数组;

 

(2) ByteArrayOutputStream(int n):在对象内部创建一个长度为nByte数组。

 

ByteArrayOutputStreamOutputStream类继承下来,所以它具writeflushclose等方法,同时它还具有以下几个特殊的方法:

 

(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

 

FileOutputStreamFileInputStream相对应,它具有以下几个构造函数:

 

(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

 

FilterOutputStreamFilterInputStream相对应,使用方法也相类似。

 

1.17 BufferedOutputStream

 

BufferedOutputStreamFilterOutputStream中继承下来,它与BufferedInputStream相对应,作用也相类似,它主要为输出流做缓冲,如:

 

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

 

由于BufferedOutputStream是缓冲数据的,所以必要时,需要使用flush方法强制将缓冲中的数据真正写入输出流中。

 

1.18 DataOutputStream

 

DataOutputStreamDataInputStream相对应,在继承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

 

PipedOutputStreamPipedInputSteam相互配合实现两个线程之间的通信,它们的定义如下:

 

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输出,而readOutPipedOutputSteam,所以它可以被另一线程接收;

 

(3) new ReadThread("writer", writeIn, System.out ),从writeIn接收数据,writeInreadOut是成对的双向管道,它接收从readOut发送过来的数据。再从标准设备中输出。

 

1.21 RandomAccessFile

 

 

1.22 StreamTokenizer

 

1.23 ObjectOutputStream

 

 

ObjectOutputStreamOutputStream继承下来,并实现了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

 

 

ObjectInputStreamObjectOutputStream相对应,它是将对象的值及类的定义等从指定的输入流读入,以便重新对象化:

 

FileInputStream in = new FileInputStream("tmp");

 

ObjectInputStream s = new ObjectInputStream(in);

 

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

 

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

 

ObjectOutputStreamObjectInputStream就可以实现对象的持久化,即要先将对象序列化保存到介质中,在必要的时候重新恢复这些对象。

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有