什么是InputStream和OutputStream?为什么我们需要使用它们?何时使用它们?

321

请有经验的人为我解释一下什么是InputStreamOutputStream

我对这两个东西的用例感到困惑。

如果您可以在解释中附上一段代码片段,那就太好了。谢谢!

10个回答

240
InputStreamOutputStream的目标是抽象不同的输入输出方式:无论流是文件、网页还是屏幕,都不应该影响使用。重要的是你能够从流中获取信息(或将信息发送到该流中)。 InputStream用于许多读取操作。 OutputStream用于许多写入操作。
以下是一些示例代码。它假设InputStream instrOutputStream osstr已经创建好了:
int i;

while ((i = instr.read()) != -1) {
    osstr.write(i);
}

instr.close();
osstr.close();

59
流通常被定义为一系列字符。更加精确地说,超过一个比特或字符被称为流。 - Gowtham
18
多个字符也可以是字符串。流(stream)和字符串(string)的区别在哪里? - Prajeet Shrestha
1
我认为流只是由0和1组成的,而不是字符。 - smilyface
@PrajeetShrestha 我认为流也意味着数据是按顺序(无随机访问)可用的,并且不是持久的(无法重新读取或修改已写入的数据)。当请求时,数据也可能不可用。例如在网络上进行流传输。 - SteveMellross
流数据意味着数据以二进制格式表示,即0和1。 - Fred Kibuchi
@PrajeetShrestha 字符串是字符的集合(所有字符都可以立即使用),流(CharacterStream)是一段时间内的字符序列。 - Saisurya Kattamuri

95

InputStream用于读取,OutputStream用于写入。它们作为装饰器相互连接,以便您可以从各种不同类型的源中读取/写入各种不同类型的数据。

例如,您可以将原始数据写入文件:

File file = new File("C:/text.bin");
file.createNewFile();
DataOutputStream stream = new DataOutputStream(new FileOutputStream(file));
stream.writeBoolean(true);
stream.writeInt(1234);
stream.close();

阅读所写的内容:

File file = new File("C:/text.bin");
DataInputStream stream = new DataInputStream(new FileInputStream(file));
boolean isTrue = stream.readBoolean();
int value = stream.readInt();
stream.close();
System.out.printlin(isTrue + " " + value);

你可以使用其他类型的流增强读/写功能。例如,你可以引入缓冲区以提高效率:

DataInputStream stream = new DataInputStream(
    new BufferedInputStream(new FileInputStream(file)));

您可以编写其他数据,例如对象:

MyClass myObject = new MyClass(); // MyClass have to implement Serializable
ObjectOutputStream stream = new ObjectOutputStream(
    new FileOutputStream("C:/text.obj"));
stream.writeObject(myObject);
stream.close();

你可以从其他不同的输入源读取:

byte[] test = new byte[] {0, 0, 1, 0, 0, 0, 1, 1, 8, 9};
DataInputStream stream = new DataInputStream(new ByteArrayInputStream(test));
int value0 = stream.readInt();
int value1 = stream.readInt();
byte value2 = stream.readByte();
byte value3 = stream.readByte();
stream.close();
System.out.println(value0 + " " + value1 + " " + value2 + " " + value3);

大多数输入流也有输出流。您可以定义自己的流来读/写特殊内容,并且有用于读取复杂内容的复杂流(例如,有用于读取/写入ZIP格式的流)。


44

来自Java教程:

流是一系列数据。

程序使用输入流从源中逐个读取数据项:

enter image description here

程序使用输出流将数据逐个写入目标位置:

enter image description here

上图所示的数据源和数据目标可以是任何包含、生成或消耗数据的内容。显然,这包括磁盘文件,但源或目标也可以是其他程序、外围设备、网络套接字或数组

来自oracle教程的代码示例

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyBytes {
    public static void main(String[] args) throws IOException {

        FileInputStream in = null;
        FileOutputStream out = null;

        try {
            in = new FileInputStream("xanadu.txt");
            out = new FileOutputStream("outagain.txt");
            int c;

            while ((c = in.read()) != -1) {
                out.write(c);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }
}

这个程序使用字节流将xanadu.txt文件逐字写入outagain.txt文件中。

查看此SE问题以了解更多关于高级字符流的细节,这些字符流是在字节流之上的包装器:

字节流和字符流


9
你需要从InputStream中读取数据并写入到OutputStream中。
例如,如果你想要复制一个文件,你需要创建一个FileInputStream来读取源文件,和一个FileOutputStream来写入到新文件。
如果你的数据是字符流,你可以使用FileReader代替InputStream,并且如果你愿意,你可以使用FileWriter代替OutputStream。
InputStream input = ... // many different types
OutputStream output = ... // many different types

byte[] buffer = new byte[1024];
int n = 0;
while ((n = input.read(buffer)) != -1)
    output.write(buffer, 0, n);

input.close();
output.close();

3
“close” 总是会“flush”,所以不行。 - pstanton
什么是缓冲区?为什么要使用它?它是如何工作的? - Nils

5

OutputStream是代表输出写入的抽象类。有许多不同的OutputStream类,它们将数据写入到特定的地方(例如屏幕、文件、字节数组、网络连接等)。InputStream类访问相同的内容,但它们从中读取数据。

这里有一个很好的基本示例,使用FileOutputStream和FileInputStream将数据写入文件,然后读取它:http://www.javacoffeebreak.com/java103/java103.html


5

:通俗易懂地说,流就是数据,最通用的流是数据的二进制表示。

输入流:如果您要从文件或其他来源读取数据,则使用的流为输入流。简单来说,输入流作为读取数据的通道。

输出流:如果您想要从源(文件等)读取和处理数据,则首先需要保存数据,而存储数据的方式就是输出流。


5
一个流是连续的液体、空气或气体流动。
Java流是从源到目的地的数据流。源或目的地可以是磁盘、内存、套接字或其他程序。数据可以是字节、字符或对象。C#或C++流也一样。一个好的比喻是Java流就像自来水从水龙头流入浴缸,然后再流入排水管道。
数据表示流的静态部分;读取和写入方法则是流的动态部分。
InputStream表示从源流出的数据流,OutputStream表示流入目的地的数据流。最后,InputStream和OutputStream是对底层数据访问(例如C文件指针)的抽象。

1

对于一种InputStream,您可以将其视为数据源的“表示”,例如文件。

FileInputStream fileInputStream = new FileInputStream("/path/to/file/abc.txt");

fileInputStream代表了该路径下的数据,您可以使用read方法从文件中读取字节。

对于其他类型的InputStream,它们接收另一个inputStream并进行进一步处理,例如解压缩。

GZIPInputStream gzipInputStream = new GZIPInputStream(fileInputStream);

gzipInputStream会将fileInputStream视为压缩数据源。当您使用read(buffer, 0, buffer.length)方法时,它将把gzip文件的一部分解压缩到您提供的缓冲区中。

我们使用InputStream的原因是,随着源中的数据变得越来越大,比如说我们有500GB的数据在源文件中,我们不想把所有东西都保存在内存中(昂贵的机器;不友好的GC分配),而且我们想要更快地获得一些结果(读取整个文件可能需要很长时间)。

对于OutputStream也是同样的道理。我们可以开始将一些结果移动到目标位置,而不必等待整个过程完成,同时减少内存消耗。

如果您想要更多的解释和示例,您可以查看这些摘要:InputStream, OutputStream, How To Use InputStream, How To Use OutputStream


0

输出流通常与数据目的地(如文件或网络等)相关联。在Java中,输出流是最终写入数据并结束的目的地。

import java.io.printstream;

class PPrint {
    static PPrintStream oout = new PPrintStream();
}

class PPrintStream {
    void print(String str) { 
        System.out.println(str)
    }
}

class outputstreamDemo {
    public static void main(String args[]) {
        System.out.println("hello world");
        System.out.prinln("this is output stream demo");
    }
}

0

继续之前其他优秀答案的讨论,用我简单的话来说:

- 如@Sher Mohammad所述,就是数据。

输入流 - 例如从文件中获取输入数据。当我有一个文件(用户上传文件 - 输入)并且想要读取其中内容时,就会使用这种情况。

输出流 - 则相反。例如,您正在生成Excel文件,并将其输出到某个位置。

“如何写入”文件是在发送方(Excel工作簿类)而不是文件输出流中定义的。

在此上下文中,请参见此处的示例。

try (OutputStream fileOut = new FileOutputStream("xssf-align.xlsx")) {
    wb.write(fileOut);
}
wb.close();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接