【问题标题】:Get an OutputStream into a String将 OutputStream 转换为字符串
【发布时间】:2010-09-18 00:42:47
【问题描述】:

在 Java 中将输出从 java.io.OutputStream 管道传输到 String 的最佳方法是什么?

说我有方法:

  writeToStream(Object o, OutputStream out)

它将某些数据从对象写入给定的流。但是,我想尽可能轻松地将此输出转换为字符串。

我正在考虑编写这样的类(未经测试):

class StringOutputStream extends OutputStream {

  StringBuilder mBuf;

  public void write(int byte) throws IOException {
    mBuf.append((char) byte);
  }

  public String getString() {
    return mBuf.toString();
  }
}

但是有更好的方法吗?我只想进行测试!

【问题讨论】:

  • 你只有 ASCII 字节吗?你不需要代码页吗?
  • 在这种情况下,是的。不过,好点子 - 我没想到。

标签: java string io stream


【解决方案1】:

我会使用ByteArrayOutputStream。完成后您可以致电:

new String( baos.toByteArray(), codepage );

或更好:

baos.toString( codepage );

对于String 构造函数,codepage 可以是Stringjava.nio.charset.Charset 的实例。可能的值为java.nio.charset.StandardCharsets.UTF_8

toString() 方法仅接受 String 作为 codepage 参数(支持 Java 8)。

【讨论】:

  • ByteArrayOutputStream 没有 toArray() 方法;它确实有 toByteArray() 。你能修复答案吗?另外,为什么不使用 baos.toString(String charsetName) 会稍微简单一些。
  • 字节数组只是二进制数据。由于(unicode)文本可以以多种不同的方式进行二进制编码,ByteArrayOutputStream 需要知道用于对字节进行编码的编码,因此它可以使用相同的编码再次将字节解码为字符串。简单地使用不带参数的 toString 是不明智的,因为您只是忽略了问题而不是解决它; Java 将使用可能正确的平台编码......或不正确。基本上是随机的。您需要找出用于将文本写入字节并将该编码传递给 toString 的编码。
  • 只是对此处引用的代码页的说明:在 Java 中,您可以使用 Charset.defaultCharset() 或 Charset.forName("specific charset");对我有用的是: new String(baos.toByteArray(), Charset.defaultCharset());
  • @WallaceBrown 使用 defaultCharset 并不比完全忽略字符集好 - 你需要在使用 toString 之前找出它是什么
  • StandardCharsets.UTF_8Charset,而不是 String。此外,该参数称为charsetName,而不是codepage
【解决方案2】:

我喜欢 Apache Commons IO 库。看看它的ByteArrayOutputStream 版本,它有一个toString(String enc) 方法以及toByteArray()。使用 Commons 项目等现有且受信任的组件可以让您的代码更小,更容易扩展和重新利用。

【讨论】:

  • 为自己节省一年的生命,并通读所有常见的 API,这样当您遇到问题时,可以推出经过全面测试且由社区拥有的解决方案。
  • 嗯,我是一个狂热的 Apache Commons 用户,但在这种情况下,我不明白为什么应该使用 Commons IO 的 ByteArrayOutputStream 而不是 JDK 自己的 java.io.ByteArrayOutputStream。后者还提供 toString(String charsetName) 和 toByteArray() 方法。需要详细说明吗?
  • 是的,由于原始上下文是流式传输和提取内容的更好方法,因此我包含了 Commons IO 示例,因为它包含用于当时未定义/有问题的机制的“write(InputStream)”方法填充输出流。我也会选择 JDK。
【解决方案3】:

效果很好

OutputStream output = new OutputStream() {
    private StringBuilder string = new StringBuilder();

    @Override
    public void write(int b) throws IOException {
        this.string.append((char) b );
    }

    //Netbeans IDE automatically overrides this toString()
    public String toString() {
        return this.string.toString();
    }
};

方法调用 =>> marshaller.marshal( (Object) toWrite , (OutputStream) output);

然后打印字符串或获取它只是引用“输出”流本身 例如,将字符串打印到控制台 =>> System.out.println(output);

仅供参考:我的方法调用 marshaller.marshal(Object,Outputstream) 用于处理 XML。与本主题无关。

这对于生产使用来说是非常浪费的,转换太多并且有点松散。这只是为了向您证明完全可以创建自定义 OuputStream 并输出字符串。但是,只需采用 Horcrux7 的方式,只需两个方法调用就可以了。

世界生活在另一天......

【讨论】:

  • 仅将一个字节转换为 char 仅适用于 ascii。像 Horcrux7 一样使用 ByteArrayOutputStream
  • 同意戴夫·雷。您不能假设您的字节是 ASCII 字符。您需要使用编码来解释字节。使用 byteArrayOutputStream.toString("UTF-8") 或 new String(byteArrayOutputStream.toByteArray(), "UTF-8")。
【解决方案4】:

这是我最终做的:

Obj.writeToStream(toWrite, os);
try {
    String out = new String(os.toByteArray(), "UTF-8");
    assertTrue(out.contains("testString"));
} catch (UnsupportedEncondingException e) {
    fail("Caught exception: " + e.getMessage());
}

其中 os 是 ByteArrayOutputStream

【讨论】:

  • @JavaJigs 我在将近 5 年前的回答底部澄清了这一点 :)
  • 考虑用StandardCharsets.UTF_8替换"UTF-8"
【解决方案5】:
baos.toString(StandardCharsets.UTF_8);

通过使用命名字符集解码字节将缓冲区的内容转换为字符串。

Java 16 - https://docs.oracle.com/

【讨论】:

  • 几乎是从已接受答案的 sn-p 复制粘贴,真丢脸
  • 我相信我的回答更中肯。事实上,它是 Oracle 文档的副本(我发布的链接)。
猜你喜欢
  • 2020-01-26
  • 2015-01-13
  • 2020-11-27
  • 2018-07-19
  • 2019-10-10
  • 2019-01-05
  • 2019-06-17
  • 2015-01-18
相关资源
最近更新 更多