将 OutputStream 转换为字符串

Get an OutputStream into a String

提问人:Adrian Mouat 提问时间:10/20/2008 最后编辑:JonikAdrian Mouat 更新时间:9/6/2022 访问量:725746

问:

在 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();
  }
}

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

Java 字符串 IO

评论


答:

694赞 Horcrux7 10/20/2008 #1

我会使用 .完成后,您可以调用:ByteArrayOutputStream

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

或更好:

baos.toString( codepage );

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

该方法只接受 a 作为参数(参见 Java 8)。toString()Stringcodepage

评论

9赞 Jonik 6/7/2009
ByteArrayOutputStream 没有 toArray() 方法;不过,它确实有 toByteArray()。你能解决答案吗?另外,为什么不使用 baos.toString(String charsetName),这会稍微简单一些。
40赞 Stijn de Witt 2/10/2011
字节数组只是二进制数据。由于 (unicode) 文本可以通过许多不同的方式对二进制进行编码,因此 ByteArrayOutputStream 需要知道使用什么编码来对字节进行编码,以便它可以使用相同的编码再次将字节解码为字符串。简单地使用没有参数的 toString 是不明智的,因为你只是忽略了问题而不是解决它;Java 将使用可能是正确的平台编码......或不。它基本上是随机的。您需要找出用于将文本写入字节的编码,并将该编码传递给 toString。
12赞 Wallace Brown 11/15/2012
这里引用的代码页需要澄清一下:在 Java 中,你可以使用 Charset.defaultCharset() 或 Charset.forName(“specific charset”);对我有用的是:new String(baos.toByteArray(), Charset.defaultCharset());
7赞 artbristol 10/18/2013
@WallaceBrown使用并不比完全忽略字符集更好 - 您需要在使用之前找出它是什么defaultCharsettoString
5赞 OrangeDog 5/14/2019
StandardCharsets.UTF_8是 ,而不是 .此外,该参数称为 ,而不是 。CharsetStringcharsetNamecodepage
54赞 Joe Liversedge 10/20/2008 #2

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

评论

12赞 Bob Herrmann 10/20/2008
节省一年的时间,并通读所有通用的 API,这样当您遇到问题时,您可以释放一个经过全面测试和社区拥有的解决方案。
17赞 Jonik 6/7/2009
嗯,我是一个狂热的 Apache Commons 用户,但在这种情况下,我不明白为什么你应该使用 Commons IO 的 ByteArrayOutputStream 而不是 JDK 自己的 java.io.ByteArrayOutputStream。后者还提供 toString(String charsetName) 和 toByteArray() 方法。想详细说明吗?
1赞 Joe Liversedge 6/9/2009
是的,由于原始上下文是流式传输和提取内容的更好方式,因此我包含了 Commons IO 示例,因为它包含一个“write(InputStream)”方法,用于填充 OutputStream 的当时未定义/可疑的机制。我也会选择JDK。
19赞 Adrian Mouat 11/4/2008 #3

这是我最终所做的:

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

评论

2赞 Adrian Mouat 6/16/2015
@JavaJigs我在大约 5 年前的回答底部澄清了这一点:)
21赞 james.garriss 12/19/2015
请考虑将 替换为 。"UTF-8"StandardCharsets.UTF_8
29赞 alcardenas 6/21/2009 #4

这很有效

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);

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

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

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

评论

12赞 Dave Ray 10/12/2009
只需将一个字节转换为 char 只能在 ascii 上工作。像 Horcrux7 一样使用 ByteArrayOutputStream
2赞 Martin Dow 4/5/2012
同意戴夫·雷(Dave Ray)的观点。您不能假定您的字节是 ASCII 字符。您需要使用编码来解释字节。使用 byteArrayOutputStream.toString(“UTF-8”) 或 new String(byteArrayOutputStream.toByteArray(), “UTF-8”)。
9赞 jschnasse 5/19/2020 #5
baos.toString(StandardCharsets.UTF_8);

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

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

-2赞 Jurgen Rutten 9/6/2022 #6

这是我所做的(不要在生产中使用它,这不是很好!但它使修复多个错误变得更加容易。

  • 创建一个包含异常的列表。

  • 创建记录器以记录异常。

  • 使用以下代码:

    private static void exceptionChecker() 抛出 Exception { if(exceptionList.isEmpty()) 返回;无事可做 :)好消息

      //create lock for multithreading
      synchronized (System.err){
          //create new error stream
          ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
          PrintStream errorOut = new PrintStream(byteArrayOutputStream);
    
          //save standard err  out
          PrintStream standardErrOut = System.err;
    
          try{
              //set new error stream
              System.setErr(errorOut);
    
              exceptionList.forEach(exception -> {
                  exception.printStackTrace();
                  System.err.println("<---------->");
              });
    
    
          } finally {
              //reset everything back to normal
              System.setErr(standardErrOut);
    
              //Log all the exceptions
              exceptionLogger.warning(byteArrayOutputStream.toString());
    
              //throw final generic exception
              throw new Exception();
          }
      }}
    

这并不好,因为您在 finally 块中抛出错误并且它会锁定错误流,但它适用于开发目的。