有没有办法在不关闭底层流的情况下关闭Writer?

时间:2013-03-04 01:30:06

标签: java sockets io outputstream

我有一个套接字,我写了一些字符数据和一些原始字节数据。对于角色数据,使用PrintWriter更容易。对于原始字节数据,直接写入OutputStream更容易。所以在我的代码中,我有这样的段:

Writer writer = new PrintWriter(outputStream);
writer.write(someText);
...
writer.flush();
// No call to writer.close(), because that would close the underlying stream.

只要我注意在开始以其他方式写入流后不写入此Writer,这很好。但是我宁愿知道如果我不小心写了一个流IOException,我会更安全(就像我关闭它一样)。

有没有办法明确阻止将来写入Writer而不关闭其基础流?

5 个答案:

答案 0 :(得分:9)

为什么呢? close()只做两件事:(1)刷新编写器,(2)在嵌套编写器上调用close()。如果您不想要(2),请自己致电flush(),不要致电close()

答案 1 :(得分:7)

简单地说,不。编写Java io流类的方式,它们总是链接关闭操作。当然,您可以创建自己的编写器实现来覆盖此行为。

答案 2 :(得分:0)

我会创建一个允许写入字符和二进制数据的特殊类,如:

class CombinedWriter extends Writer {
    private boolean isWritingBinary;
    private Writer mWriter;
    private OutputStream mOutputStream;
    public void write(byte[] bytes) {
        // flush the writer if necessary
        isWritingBinary = true;
        mOutputStream.write(bytes);
    }
    public void write(String string) {
        // flush if necessary
        isWritingBinary = false;
        mWriter.write(string);
    }
    public void flush() {
        // ...
    }
    public void close() {
        // ...
    }
}

它可以延伸或不延伸Writer;在后一种情况下,您不需要覆盖代码中未使用的方法。

编写器刷新的技巧仍然存在,但它本地化为一个类;此外,如果某个未来版本中的技巧中断,可以重写该类以消除该技巧(可能需要从Android源中借用一部分代码)。

答案 3 :(得分:0)

这是如何将OutputStream用于字符和二进制数据:

byte strBin[] = someText.getBytes("UTF-8");
outputStream.write(strBin);

如果您需要different编码,请替换“UTF-8”。

答案 4 :(得分:0)

感谢您的提问!我遇到了完全相同的问题,而且很容易解决。通过阅读您的问题,听起来您可能正在尝试完全按照我的想法去做,所以我想通过提供适合我的解决方案来提供帮助。

在我的情况下,我试图为jpg编写HTTP响应,在这种情况下,文本标题部分后面将是二进制数据。这里的流是Java OutputStream的{​​{1}}。

我当时使用Socket将文本写入套接字流,但是随后我需要写入二进制数据。有一个简单的解决方案,它适用于二进制数据紧随文本数据之后且二进制数据之后没有文本数据的情况。

只需在流上打开PrintWriter,然后使用writer将文本打印到流中,直到所有文本都被写入为止。然后将Printwriter刷新到流中,但不要关闭它(这将关闭基础流,该流必须保持打开状态)。最后,将二进制数据直接写入流中。

最后,您可以简单地关闭PrintWriter来关闭基础流。

如果使用下面提供的类,您将:

  1. 通过为基础PrintWriter提供HttpStreamWriterImpl来构造OutputStream
  2. 根据需要反复致电Socket
  3. 根据需要致电writeLine()
  4. 完成后致电writeBinary()

示例:

close()