有没有办法在不关闭底层流的情况下关闭 Writer?
Posted
技术标签:
【中文标题】有没有办法在不关闭底层流的情况下关闭 Writer?【英文标题】:Is there a way to close a Writer without closing the underlying stream? 【发布时间】:2013-02-18 01:05:09 【问题描述】:我有一个套接字,我可以在其中写入一些字符数据和一些原始字节数据。对于字符数据,使用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
?
【问题讨论】:
【参考方案1】:简单地说,不。 Java io 流类的编写方式,它们总是链接关闭操作。当然,您可以创建自己的编写器实现来覆盖此行为。
【讨论】:
【参考方案2】:为什么? close()
只做两件事:(1)刷新写入器和(2)在嵌套写入器上调用close()
。如果您不想(2),请自己致电flush()
,并且根本不要致电close()
。
【讨论】:
【参考方案3】:我会创建一个允许写入字符和二进制数据的特殊类,例如:
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 源代码中借用一部分代码)。
【讨论】:
【参考方案4】:这是对字符和二进制数据都使用 OutputStream 的方法:
byte strBin[] = someText.getBytes("UTF-8");
outputStream.write(strBin);
如果您想要different 编码,请替换“UTF-8”。
【讨论】:
最好使用java.nio.charset
包中的 StandardCharsets.UTF_8
,而不是在 java 7+ 上使用字符串文字对名称进行硬编码【参考方案5】:
感谢您的提问!我遇到了完全相同的问题,而且很容易解决。从阅读您的问题来看,您可能正在尝试做我想做的事情,所以我想通过提供对我有用的解决方案来提供帮助。
在我的例子中,我试图为 jpg 编写 HTTP 响应,在这种情况下,文本标题部分将跟随二进制数据。这里的流是Java Socket
的OutputStream
。
我使用PrintWriter
将文本写入套接字流,但随后我需要写入二进制数据。有一个简单的解决方案,它适用于二进制数据跟随文本数据的情况,并且二进制数据之后没有更多的文本数据。
只需在流上打开一个Printwriter
并使用编写器将文本打印到流中,直到所有文本都被写入。然后将PrintWriter
刷新到流中,但不要关闭它(这会关闭必须保持打开的基础流)。最后,将二进制数据直接写入流中。
最后,您可以简单地关闭 PrintWriter
以关闭底层流。
如果使用下面提供的类,你会:
-
通过为基础
Socket
提供OutputStream
来构造HttpStreamWriterImpl
。
根据需要反复拨打writeLine()
。
如有需要,请致电writeBinary()
。
完成后致电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();
【讨论】:
以上是关于有没有办法在不关闭底层流的情况下关闭 Writer?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不失去对 React Native 的关注的情况下关闭键盘。(至少显示光标)
有啥方法可以在不关闭其 BaseStream 的情况下关闭 StreamWriter?
如何在不关闭模式的情况下关闭从 modalViewController 推送的 viewController?