如何在不关闭OutputStream对象的情况下强制刷新它?

时间:2012-04-15 22:27:11

标签: java android sockets outputstream

我的问题在于以下假设,我希望这些假设是正确的,因为我相信这些是在谷歌搜索我的问题时阅读它们:

  1. 关闭套接字的OutputStream也会关闭套接字
  2. OutputStream的flush()方法不执行任何操作
  3. 所以我基本上需要从我的OutputStream对象中刷新数据,以使我的应用程序正常工作。

    如果您对细节感兴趣,请参阅以下两个链接:

    Weird behavior : sending image from Android phone to Java server (code working)

    关闭OutputStream解决了此问题。这样做会将所有数据刷新到套接字的另一端并使我的应用程序进一步工作但是这个修复程序很快引起了问题2 - 相应的套接字也被关闭了:

    SocketException - 'Socket is closed' even when isConnected() returns true

7 个答案:

答案 0 :(得分:6)

您可以调用OutputStream的flush方法而不是close。从OutputStream继承的具体类将覆盖flush()以执行除了任何操作之外的其他操作(将数据写入文件或通过网络发送)。

答案 1 :(得分:2)

  

OutputStream的flush()方法什么都不做。

这是不正确的。

flush()类提供的OutputStream的基本实现确实没有做任何事情。但是,您的应用将调用您正在使用的实际流类提供的该方法的版本。如果流类没有直接写入语义,它将覆盖flush()以执行所需的操作。

简而言之,如果需要刷新(并且Socket输出流需要 ),那么调用flush()将做正确的事情。 (如果某些互联网消息来源告诉您,否则它是错误的,或者您误解了它。)


仅供参考,基地OutputStream实施flush()作为无操作的原因是:

  • 某些输出流类在刷新时不需要执行任何操作;例如ByteArrayOutputStream
  • 对于flush()不是无操作的流类,无法在基类级别实现该操作。

他们可以(理论上)设计流API,以便OutputStream是抽象类(和flush()抽象方法)或接口。但是,在Java 1.0之前,这个API被有效地冻结了,当时没有足够的实际Java编程经验来实现API设计不是最理想的。

答案 2 :(得分:1)

  

关闭套接字的OutputStream也会关闭套接字

真。

  

OutputStream的flush()方法不执行任何操作

假。有覆盖。请参阅Javadoc了解FilterOutputStream.flush()BufferedOutputStream.flush()ObjectOutputStream.flush(),仅举几例。

因此,您的初始问题不存在,因此您不需要导致问题#2的“解决方案”。

答案 3 :(得分:0)

你真的需要冲洗吗?我也有一个问题,c#服务器上的监听器无法接收从android发送的数据(我试图同步获取数据)。

我确信这是因为在Android方面,以下代码没有刷新。

OutputStream str = btSocket.getOutputStream();
str.write(data_byte);
// "This implementation does nothing"
str.flush();

事实证明,如果我在服务器的监听器上使用异步数据检索 - 它会获取数据,并且客户端不需要flush()!

答案 4 :(得分:0)

我会捅它。我遇到了同样的问题。关闭输出流是我能够"冲洗"的唯一方法。数据。但是因为我仍然需要输出流不是一个选项。所以我发送字节数组长度,out.writeInt,然后发送数组本身。当所有字节都被读取时,即buffer.length == in.readInt()我打破循环

    ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    byte[] fileBytes;
    int n;
    int length;

    try
    {
        size = in.readInt();

        while((n = in.read(buffer)) != -1)
        {
            dataBuffer.write(buffer, 0, n);

            if(dataBuffer.toByteArray().length == length)
            {
                fileBytes = dataBuffer.toByteArray(); break;
            }
        }
    }

答案 5 :(得分:0)

我遇到了同样的问题。 在流的末尾添加“\ n”。 flush可以正常工作但是destinary不知道消息是否已经结束

答案 6 :(得分:0)

在Android flush()上的

是什么都不做(基于api 23的例子)

    DELETE
    FROM ASPNETUSERS
    WHERE Id = 'X'
  

要在不关闭套接字的情况下刷新输出流,您可以关闭输出:

public Socket() {
    this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl();
    this.proxy = null;
}

public class PlainSocketImpl extends SocketImpl {

    @Override protected synchronized OutputStream getOutputStream() throws IOException {
        checkNotClosed();
        return new PlainSocketOutputStream(this);
    }


}

private static class PlainSocketOutputStream extends OutputStream {
        // doesn't override base class flush();
}

- 这将关闭WRITE文件描述符。

而不是使用输出流,您可以直接写入文件描述符,或者使用OutputStream创建自己的Socket实现,它将覆盖flush方法(例如在c中使用Berkeley socket实现(通过本地电话)。