“你好,阿米戈!今天,我们将再次探讨 InputStream 和 OutputStream 的工作原理。最初的解释实际上有点过于简化了。这二者不是接口。它们是抽象类,并且甚至有几个已实现的方法。现在我们来看一下它们所包含的方法:”
InputStream 方法 | 方法的用途 |
---|---|
|
此方法立即将一个字节块读入缓冲区(字节数组),直至缓冲区已满或源中不再有可供读取的字节。 该方法返回实际读取的字节数(可以小于数组的长度) |
|
此方法读取一个字节并返回该字节。结果被拓展为 int 以便于查看。如果不再有可供读取的字节,则该方法返回 -1。 |
|
此方法返回未读(可用)字节数。 |
|
此方法“关闭”流。使用完流之后,可以调用此方法。 然后,对象执行关闭文件所需的整理操作,等等。 此时,你无法再从流中读取任何数据。 |
“因此,我们不仅可以读取单个字节,还可以读取整个块?”
“完全正确。”
“我们也可以写入整个块吗?”
“是的,我们来看一下:”
OutputStream 方法 | 方法的用途 |
---|---|
|
此方法写入一个字节。int 类型窄化为一个字节。多余部分被直接丢弃。 |
|
此方法写入一个字节块。 |
|
此方法写入字节块的一部分。在字节数组可能尚未完全填充的情况下使用。 |
|
如果流在内部存储尚未写入的任何数据,则此方法强制写入数据。 |
|
此方法“关闭”流。使用完流之后,可以调用此方法。 然后,对象执行关闭文件所需的整理操作,等等。你无法再将数据写入流中,并自动调用 flush。 |
“如果我们一次读取整个块而不是单个字节,那么文件复制代码会是什么样?”
“嗯。就像下面这样:”
复制磁盘上的文件
public static void main(String[] args) throws Exception
{
//Create a stream to read bytes from a file
FileInputStream inputStream = new FileInputStream("c:/data.txt");
//Create a stream to write bytes to a file
FileOutputStream outputStream = new FileOutputStream("c:/result.txt");
byte[] buffer = new byte[1000];
while (inputStream.available() > 0) //as long as there are unread bytes
{
//Read the next block of bytes into buffer, and store the actual number of bytes read in count.
int count = inputStream.read(buffer);
outputStream.write(buffer, 0, count); //Write a block (part of a block) to the second stream
}
inputStream.close(); //Close both streams. We don't need them any more.
outputStream.close();
}
“我对缓冲区完全了解,但是这个 count 变量是什么?”
“当我们从文件中读取最新的数据块时,举例来说,我们可能会得到 328 个字节,而不是 1000 个字节。因此在写入数据时,我们需要指出我们并不写入整个块,而只写入前 328 个字节。”
当我们读取最后一个块时,read 方法将返回实际读取的字节数。每次读取一个块时,我们会获取 1000 个字节,而在读取最后一个块时,我们获取 328 个字节。
因此在写入块时,我们指出不要写入缓冲区中的所有字节,而只写入 328(即存储在 count 变量中的值)个字节。
“现在我全明白了。谢谢你,艾莉。”
GO TO FULL VERSION