6

我有一个套接字,我向其中写入了一些字符数据和一些原始字节数据。对于字符数据,使用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有没有办法在不关闭其底层流的情况下明确防止未来写入 a ?

4

5 回答 5

10

为什么?close()只做两件事:(1)刷新作者和(2)调用close()嵌套作者。如果您不想要(2),请给flush()自己打电话,根本不要打电话close()

于 2013-03-04T08:38:49.810 回答
7

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

于 2013-03-04T01:37:59.403 回答
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;在后一种情况下,您不需要覆盖代码中未使用的方法。

writer flush 的技巧仍然存在,但它被本地化为一个类;此外,如果该技巧在未来的某个版本中出现问题,则可能会重写该类以消除该技巧(可能需要从 Android 源代码中借用一部分代码)。

于 2015-02-24T13:10:28.760 回答
0

这是将 OutputStream 用于字符和二进制数据的方法:

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

如果您想要不同的编码,请替换“UTF-8” 。

于 2017-04-25T21:15:52.453 回答
0

谢谢提问!我遇到了完全相同的问题,而且很容易解决。通过阅读您的问题,听起来您可能正在尝试做我想做的事情,所以我想通过提供对我有用的解决方案来提供帮助。

在我的情况下,我试图为 jpg 编写 HTTP 响应,在这种情况下,文本标题部分后面将跟随二进制数据。这里的流是OutputStreamJava 的Socket

我正在使用 aPrintWriter将文本写入套接字流,但随后我需要写入二进制数据。有一个简单的解决方案,它适用于二进制数据跟随文本数据的情况,并且在二进制数据之后没有更多的文本数据。

只需Printwriter在流上打开 a 并使用 writer 将文本打印到流中,直到所有文本都被写入。然后将其刷新PrintWriter到流中,但不要关闭它(这会关闭必须保持打开的底层流)。最后,将二进制数据直接写入流。

最后,您可以简单地关闭PrintWriter以关闭底层流。

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

  1. HttpStreamWriterImpl通过为OutputStream底层提供 来构造Socket
  2. writeLine()根据需要反复调用。
  3. writeBinary()如果/根据需要打电话。
  4. close()完成后打电话。

例子:

public class HttpStreamWriterImpl implements Closeable
{
    private @NotNull OutputStream stream;
    private @NotNull PrintWriter printWriter;

    public HttpStreamWriterImpl(@NotNull OutputStream stream)
    {
        this.stream = stream;
        this.printWriter = new PrintWriter(stream, true, UTF_8);
    }

    public void writeLine(@NotNull String line)
    {
        printWriter.print(line);
        printWriter.print(HTTP_LINE_ENDING);
    }

    public void writeBinary(@NotNull byte[] binaryContent) throws IOException
    {
        printWriter.flush();
        stream.write(binaryContent);
        stream.flush();
    }

    @Override
    public void close()
    {
        printWriter.close();
    }
}
于 2018-12-06T03:46:10.707 回答