13. Java IO: InputStream

想要查看此教程的目录请点击:Java IO教程目录贴地址


InputStream是Java IO中所有输入流的基类。它的子类包括FileInputStream,BufferedInputStream和PushbackInputStream等。想要查看所有详细的列表,请看“Java IO Overview”章节。

InputStreams and Sources

InputStream经常被用来连接一些数据源,例如文件,网络连接,管道等等。查看更详细的信息参考“Java IO Overview”章节

InputStream例子

它用来读取字节数据,每次读取一个字节。下面是一个相关例子:

nputStream inputstream = new FileInputStream("c:\\data\\input-text.txt");

int data = inputstream.read();
while(data != -1) {
  //do something with data...
  doSomethingWithData(data);

  data = inputstream.read();
}
inputstream.close();

这个例子中创建了一个FileInputStream实例。FileInputStream是InputStream的子类所以它可以InputStream类型的变量。
注意:为了代码清晰,这里并没有考虑处理异常的情况。想学习更多可以看“Java IO Exception Handling”

Java7开始,你可以用try-with-resources去确保InputStream在使用后可以关闭。具体的用法可以参考上面Java异常处理的文章,但是这里有一个例子:

try( InputStream inputstream = new FileInputStream("file.txt") ) {

    int data = inputstream.read();
    while(data != -1){
        System.out.print((char) data);
        data = inputstream.read();
    }
}

只要线程已经执行出try代码块,inputstream就会被关闭。

read()

InputStream的read()方法返回一个int类型的值,这个值是每次读取的字节的值。下面是一个相关的例子:

int data = inputstream.read();

你也可以把int值强转成为一个char类型的:

char aChar = (char) data;

InputStream的子类有可能扩展了read()方法。例如,DataInputStream允许读取java基本类型,像int、long、float、double、boolean等等。当然这些有相应的方法,readBoolean(),readDouble()等等。

Stream的结束

如果read()方法返回 -1,就说明流到已经全部读取完毕。这里的 -1 是int类型的,不是byte或short。这里是有些不同的!
当流去读完毕的时候,你可以关闭它了

read(byte[])

InputStream有两个read()方法,参数是一个字节数组。这些方法是:

  • int read(byte[])
  • int read(byte[], int offset, int length)

每次读取一个字节数组显然要比每次读取一个字节要快的多,所以只要有可能,你可以使用这类的方法来替代read()方法。

read(byte[])方法会读取所有数据到数组中。它会返回一个int值,来告诉实际读取的字节数。万一实际读取的字节数要比提供的字节少,那么字节数组的其余部分将包含与读取开始之前所做的相同的数据。要记住去检查返回的int值,看实际取得的字节数有多少。
read(byte[], int offset, int length)方法也是读数组到数组中,但是可以根据参数来规定开始的偏移量和一共读取多少长度。返回值和read(byte[])方法的含义相同。

两个方法相同的地方都是如果返回值是 -1 ,代表读取结束。

下面的例子为如何使用InputStream的read(byte[])方法:

InputStream inputstream = new FileInputStream("c:\\data\\input-text.txt");

byte[] data      = new byte[1024];
int    bytesRead = inputstream.read(data);

while(bytesRead != -1) {
  doSomethingWithData(data, bytesRead);

  bytesRead = inputstream.read(data);
}
inputstream.close();

首先,上面代码创建了一个字节数组。然后创建了一个叫bytesRead的int类型变量,去接受每次调用read(byte[])方法的返回值。
在循环里,doSomethingWithData()方法被循环调用,传递进去读了多少字节和字节数组。在循环的最后把数据重新读到数组一遍。

不用花太多精力放在研究怎么样使用read(byte[], int offset, int length)方法来替换read(byte[])。你完全可以在任何时候用read(byte[], int offset, int length)替换掉read(byte[])方法。

mark()和reset()

InputStream类中有两个方法mark()和reset(),但是它的子类不一定有支持(或者说子类有没有重写此方法)。

如果一个InputStream的子类支持这两个方法,子类会重写markSupported()方法并返回 true。相反的,如果返回false,则子类不支持这两个方法。

mark()方法在InputStream设置一个内部的标记,标记在流中哪个数据到目前为止已经被读取。使用InputStream的代码,可以根据这个标记位来继续读取数据。

在读取流的过程汇总,如果想退回到标记的那点上,可以调用reset()方法。然后InputStream退回到标记位上,开始从这个位置开始返回数据。这当然会导致多次返回一些数据

当实现一个解析器时,会经常用到这两个方法。解析器读取一个InputStream时会提前读,如果解析器没有找到它想要的,他可能需要回退并且将已读数据和其他的数据进行匹配。

你可能感兴趣的:(13. Java IO: InputStream)