将ByteArrayInputStream的内容转换为字符串

40

我看了这篇文章,但是我不太明白。我看过这个,但没有看到使用ByteArrayOutputStreamByteArrayInputStream转换为String的正确示例。

如果要将ByteArrayInputStream的内容作为String检索出来,是否建议使用ByteArrayOutputstream,还是有更好的方法?

我考虑了这个例子并扩展了ByteArrayInputStream并利用装饰器在运行时增加功能。你认为这是比使用ByteArrayOutputStream更好的解决方案吗?


1
你可能需要一个InputStreamReader,就像你提供的第二个链接中所描述的那样。ByteArrayOutputStream不会将字节转换为字符。 - Dawood ibn Kareem
你真的有一个ByteArrayInputStream(这意味着你有一个byte[]),还是只有一个InputStream? - Brett Okken
@BrettOkken 我有一个ByteArrayInputStream,它的构造函数接受一个字节数组(大小不同)。 - Mushy
@DavidWallace,第二个链接中有一个回复使用了InputstreamReader:问题在于它只读取到第一个行分隔符为止。它假设你要查找的字符串不包含任何行分隔符。通常情况下是这样的,但如果不是,这种方法就不会真正起作用。这就是我不继续使用那个示例的原因。 - Mushy
但是你可以不断地从它中读取,直到它变为空。 - Dawood ibn Kareem
5个回答

55

ByteArrayOutputStream可以从任何InputStream读取数据,并在结束时生成一个byte[]

但是,使用ByteArrayInputStream更加简单:

int n = in.available();
byte[] bytes = new byte[n];
in.read(bytes, 0, n);
String s = new String(bytes, StandardCharsets.UTF_8); // Or any encoding.

对于一个ByteArrayInputStreamavailable()方法返回总字节数。


补充 2021-11-16

自 Java 9 起,你可以使用更短的readAllBytes方法。

byte[] bytes = in.readAllBytes();

回复评论:使用ByteArrayOutputStream

ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[8192];
for (;;) {
    int nread = in.read(buf, 0, buf.length);
    if (nread <= 0) {
        break;
    }
    baos.write(buf, 0, nread);
}
in.close();
baos.close();
byte[] bytes = baos.toByteArray();

这里的 InputStream 可以是任何输入流。


自 Java 10 开始,还有一个 ByteArrayOutputStream#toString(Charset) 方法。

String s = baos.toString(StandardCharsets.UTF_8);

1
一个 ByteArrayOutputStream 怎样从一个 ByteArrayInputStream 中读取数据? - Mushy
2
我已经扩展了答案。原则上,一个循环从InputStream读取并写入ByteArrayOutputStream。出于传统,I/O缓冲区的大小通常是2的幂次方。 - Joop Eggen
同意使用2的幂次方大小;我喜欢这个,谢谢。 - Mushy
InputStream.available() 函数的 javadoc 中可以得知:使用该方法的返回值来分配一个旨在容纳此流中所有数据的缓冲区是不正确的。 - nucatus
@nucatus,没错,我没有说in就是那个ByteArrayInputStream。对于ByteArrayInputStream#available(),我们可以这样使用。 - Joop Eggen

29

为什么没有人提到org.apache.commons.io.IOUtils

import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;

String result = IOUtils.toString(in, StandardCharsets.UTF_8);

只需要一行代码。


3
我添加了两个必需的“import”语句,以便不是每个人都需要搜索它们。抱歉……现在不只是一行代码了 ;) - dokaspar
1
抱歉,我认为这个答案不正确。因为如果您的输入是ByteArrayInputStream,您将会得到编译错误。这个函数的正确输入应该是InputStream。 - vicangel

10

Java 9+解决方案:

new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);

2

使用Scanner,并将ByteArrayInputStream传递给其构造函数,然后从Scanner中读取数据,可以参考以下示例:

ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(new byte[] { 65, 80 });
Scanner scanner = new Scanner(arrayInputStream);
scanner.useDelimiter("\\Z");//To read all scanner content in one String
String data = "";
if (scanner.hasNext())
    data = scanner.next();
System.out.println(data);

如果我有 XMLHTML 文档,我是否能够无限制地阅读它? - Mushy
是的,没有限制。 - Mifmif

1

不错的解决方案。但是,我需要先将我的ByteArrayInputStream连接到我的ByteArrayOutputStream中。这该怎么做? - Mushy
1
需要强调的是,Base64.Encoder 是在 Java 8 中发布的。 :) - Jacobi
1
应该是 String s = new String(Base64.getEncoder().encode(baos.toByteArray())); 虽然谢谢。 - Siddharth Gharge
正如@SiddharthGharge所说,编码器的创建是错误的。此外,问题是关于InputStream而不是OutputStream。 - akostadinov

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