Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 有没有一种方法可以在不关闭底层流的情况下关闭Writer?_Java_Sockets_Io_Outputstream - Fatal编程技术网

Java 有没有一种方法可以在不关闭底层流的情况下关闭Writer?

Java 有没有一种方法可以在不关闭底层流的情况下关闭Writer?,java,sockets,io,outputstream,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

我有一个套接字,我在其中写入一些字符数据和一些原始字节数据。对于字符数据,更容易使用
PrintWriter
。对于原始字节数据,直接写入
OutputStream
更容易。因此,在我的代码中,我有如下片段:

Writer writer = new PrintWriter(outputStream);
writer.write(someText);
...
writer.flush();
// No call to writer.close(), because that would close the underlying stream.
只要我小心不要在开始以其他方式写入流之后写入此
编写器
,就可以了。但我更希望安全地知道,如果我不小心写入流,我会得到一个
IOException
(如果我关闭了它,我也会这样做)


有没有一种方法可以在不关闭底层流的情况下显式防止将来对
编写器的写入?

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

为什么
close()
只做两件事:(1)刷新写入程序;(2)调用嵌套写入程序上的
close()
。如果不需要(2),请自己调用
flush()
,根本不调用
close()

我将创建一个特殊类,允许同时写入字符和二进制数据,类似于:

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源代码借用一部分代码)。

以下是如何对字符和二进制数据使用OutputStream:

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

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

谢谢您的询问!我也有同样的问题,而且很容易解决。通过阅读你的问题,听起来你可能正试图做我想做的事情,所以我想通过给出对我有效的解决方案来帮助你

在我的例子中,我试图为jpg编写一个HTTP响应,在这种情况下,文本头部分后面将跟随二进制数据。这里的流是Java
Socket
OutputStream

我使用
PrintWriter
将文本写入套接字流,但随后需要写入二进制数据。有一个简单的解决方案,它的工作原理与文本数据之后是二进制数据的情况相同,并且在二进制数据之后没有更多的文本数据

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

最后,您只需关闭
PrintWriter
即可关闭底层流

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

  • 通过为底层
    套接字提供
    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();
        }
    }
    

    最好使用
    java.nio.charset
    包中的
    StandardCharsets.UTF_8
    ,而不是在Java7上使用字符串文字硬编码名称+