只接受写入ByteArrayOutputStream对象的部分消息

时间:2016-04-22 14:25:32

标签: java bytearrayoutputstream

我正在尝试获取SOAPMessage对象的原始xml,并且我正在使用ByteArrayOutputStream类执行此操作,但是一旦将压缩附件添加到消息对象中,它就失去了可读性。

这是我的代码:

ByteArrayOutputStream out = new ByteArrayOutputStream();
message.writeTo(out);
strMsg = new String(out.toByteArray());

其中message是SOAPMessage对象。 问题是,当我将它打印到stdout或日志或其他输出时,strMsg可能很大并且包含压缩附件的字节数据。有没有办法在将消息写入ByteArrayOutputStream对象时截断它?我知道,我可以很容易地截断strMsg,但我没有理由收集ByteArrayOutputStream中的所有数据。

1 个答案:

答案 0 :(得分:1)

  

我知道,我可以很容易地截断strMsg,但我没有看到收集ByteArrayOutputStream中所有数据的理由。

问题是您只能使用writeTo方法,并且该方法用于输出整个消息。

您可以创建ByteArrayOutputStream的自定义变体,它只接受指定数量的字节。当writeTo超过限制时,您的类需要抛出IO异常。

实际问题是创建和抛出异常是昂贵的。这是咒语的真正基础"仅在特殊情况下使用例外情况" - https://softwareengineering.stackexchange.com/questions/184654/ive-been-told-that-exceptions-should-only-be-used-in-exceptional-cases-how-do。如果要记录大量SOAP消息,那可能是个问题。

异常创建/抛出的主要性能瓶颈实际上是异常对象的创建:特别是Throwable构造函数调用fillInStacktrace来捕获堆栈帧的部分。有几种方法可以改善这种情况:

  • 每次都可以创建一个实例,将其缓存在" global"而不是new - 每次都有一个异常对象。并多次重复使用。

  • 如果异常是自定义异常,您可以覆盖其fillInStacktrace方法,不执行任何操作。

在这两种情况下,如果尝试打印堆栈跟踪,最终会出现异常,从而导致错误的结果。但是,如果您使用例外来实现"非例外"代码路径('因为你没有真正的选择!)那么这可能不相关。

我的解决方案有一个变体,其中自定义字节接收器类默默地丢弃字节而不是抛出异常。这样可以避免异常的成本(但请参见上文),但它并没有避免{@ 1}}在将大型SOAP消息序列化为已经停止监听的字节接收器时所做的不必要的工作"。

另一件需要注意的事情是,如果使用UTF-8等多字节字符编码,在一定数量的字节容易中断后会截断。考虑如果截断100个字节会发生什么,并且第100个字节位于字符的中间。请注意,如果writeOut包含默认字符集中无效字符的序列,则new String(byte[])的行为未指定。