生成输入流的资源有效方式是什么?

What is the resource efficient way to generate inputstream?

我是 Java IO 的新手。目前,我有这些代码行可以生成基于字符串的输入流。

String sb = new StringBuilder();
for(...){
   sb.append(...);
}
String finalString = sb.toString();
byte[] objectBytes = finalString.getBytes(StandardCharsets.UTF_8);
InputStream inputStream = new ByteArrayInputStream(objectBytes);

也许,我误解了什么,但是除了使用 getBytes() 之外,还有更好的方法从 String 生成 InputStream 吗?

例如,如果 String 真的很大,有 50MB,并且由于资源限制而无法创建它的另一个副本(getBytes() 用于另一个 50MB),它可能会引发内存不足错误。

我只是想知道上面的代码行是否是从字符串生成 InputStream 的有效方法。例如,有没有一种方法可以 "stream" String 进入输入流而不使用额外的内存?就像在 String 之上的类似 Reader 的抽象?

尝试这样的事情(不保证打字错误:)

BufferedReader reader = new BufferedRead(new InputStreamReader(yourInputStream), Charset.defaultCharset());
final char[] buffer = new char[8000];
int charsRead = 0;
while(true) {
    charsRead = reader.read(buffer, 0, 8000);
    if (charsRead == -1) {
        break;
    }
    // Do something with buffer
}

InputStreamReader 使用 Charset 从 byte 转换为 char。 BufferedReader 允许您读取字符块。

对于非常大的输入流,您可能希望分块处理输入,而不是将整个流读入内存然后进行处理。

我认为您要查找的是 StringReader,其定义为:

A character stream whose source is a string.

要有效地使用它,您需要确切地知道您希望读取的字节所在的位置。它支持随机和顺序访问,因此如果您愿意,您可以通过 char 阅读整个 Stringchar

您正在生成数据,实际上是 写入 并且您想几乎立即使用数据,读取

Unix 技术是将一个进程的输出通过管道传输到另一个进程的输入。在 java 中,至少还需要两个线程。他们将同步生产和消费。

PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(in);
new Thread(() -> writeAllYouveGot(out)).start();
readAllYouveGot(in);

在这里,我启动了一个用于编写的线程,它使用一个在 out 上调用一些自定义方法的 Runnable。而不是使用 new Thread 你可能更喜欢 ExecutorService.

管道 I/O 很少使用,尽管异步行为是最佳的。甚至可以在 PipedInputStream 上设置管道的大小。很少使用的原因是需要第二个线程。

为了完成事情,人们可能会将二进制 Input/OutputStreams 包装在 new InputStreamReader(in, "UTF-8")new OutputStreamWriter(out, "UTF-8").