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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10166701/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 23:53:36  来源:igfitidea点击:

How can you force a flush on an OutputStream object without closing it?

javaandroidsocketsoutputstream

提问by GrowinMan

My question lies on the following assumptions which I hope are true, because I believe these as I read them while Googling my problems:

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

  1. Closing a Socket's OutputStream closes the socket too
  2. The flush() method of OutputStream does nothing
  1. 关闭套接字的 OutputStream 也会关闭套接字
  2. OutputStream 的 flush() 方法什么都不做

So I basically need to anyhow flush the data out of my OutputStream object for my app to work.

所以我基本上需要以任何方式将数据从我的 OutputStream 对象中清除,以便我的应用程序工作。

If you're interested in details then please see the following two links :

如果您对详细信息感兴趣,请查看以下两个链接:

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

. 奇怪的行为:将图像从 Android 手机发送到 Java 服务器(代码工作)

This issue was resolved by closing the OutputStream. Doing that flushed all the data to the other end of the socket and made my app working further but this fix soon gave rise to problem number 2 - the corresponding socket also gets closed :

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

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

. SocketException - “套接字已关闭”,即使 isConnected() 返回 true

回答by smichak

You can call the flush method of OutputStream instead of close. The concrete classes inheriting from OutputStream will override flush() to do something other than nothing (writing the data to a file or sending it over the network).

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

回答by Stephen C

The flush() method of OutputStream does nothing.

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

This is incorrect.

这是不正确的。

It is true that the base implementation of flush()provided by the OutputStreamclass does nothing. However, your app will be calling the version of that method that is provided by actualstream class that you are using. If the stream class doesn't have direct write semantics, it will override flush()to do what is required.

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

In short, if a flush is required (and it isrequired for a Socket output stream), then calling flush()will do the right thing. (If some internet source tells you otherwise it is either wrong or you are misinterpreting it.)

总之,如果需要冲洗(它需要一个Socket输出流),然后调用flush()会做正确的事。(如果某些互联网资源告诉您否则它要么是错误的,要么是您误解了它。)



FYI, the reason that the base OutputStreamimplements flush()as a no-op is that:

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

  • some output stream classes don't need to do anything when flushed; e.g ByteArrayOutputStream, and
  • for the stream classes where flush()is not a no-op, there is no way to implement the operation at the base class level.
  • 一些输出流类在刷新时不需要做任何事情;例如ByteArrayOutputStream,和
  • 对于flush()非空操作的流类,无法在基类级别实现操作。

They could (in theory) have made designed the stream APIs so that OutputStreamwas an abstract class (and flush()an abstract method) or an interface. However this API was effectively frozen prior to Java 1.0, and at that time there wasn't enough experience with practical Java programming to realize that the API design was suboptimal.

他们可以(理论上)设计流 API,使其OutputStream成为抽象类(和flush()抽象方法)或接口。然而,在 Java 1.0 之前,这个 API 被有效地冻结了,当时没有足够的实际 Java 编程经验来意识到 API 设计是次优的。

回答by user207421

Closing a Socket's OutputStream closes the socket too

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

True.

真的。

The flush() method of OutputStream does nothing

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

False. There are overrides. See the Javadoc for FilterOutputStream.flush(), BufferedOutputStream.flush(), ObjectOutputStream.flush(), to name a few.

错误的。有覆盖。请参阅 Javadoc 以了解FilterOutputStream.flush()BufferedOutputStream.flush()ObjectOutputStream.flush()等。

So your initial problem is non-existent, so you have no need for the 'solution' that causes problem #2.

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

回答by infografnet

Do you really need to flush? I also had an issue, where listener on c# server couldn't receive data sent from android (I tried to get the data synchronously).

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

I was sure that this is because on Android side, the following code didn't flush.

我确定这是因为在 Android 端,以下代码没有刷新。

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

It turned out, that if I use asynchronous data retrieval on server's listener - it gets the data, and no flush() on client's side is required!

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

回答by everforth

I'll take a stab at it. I was having the same problem. closing the outputstream is the only way i can "flush" the data. but since i still need the outputstream that's not an option. so 1st i send the byte array length, out.writeInt, then the array itself. when all bytes have been read ie buffer.length == in.readInt() i break loop

我会尝试一下。我遇到了同样的问题。关闭输出流是我可以“刷新”数据的唯一方法。但由于我仍然需要输出流,这不是一个选项。所以首先我发送字节数组长度,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;
            }
        }
    }

回答by user3248022

I had the same problem. Add "\n" at the end of the stream. flush works but the destinary does not know if the message ended

我有同样的问题。在流的末尾添加“\n”。刷新有效,但目的地不知道消息是否结束

回答by ceph3us

YES on Android flush() do nothing (example based on api 23)

YES on Android flush() 什么都不做(基于 api 23 的例子)

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();
}

to flush output stream without closing socket you can shutdown output:

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

protected void shutdownOutput() throws IOException

-- this will close WRITE file descriptor.

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

instead of using output stream you can write directly to file descriptoror by creating own Socket implementation with OutputStream which will override flush method (for example using a Berkeley socketimplementation in c (via native call).

而不是使用输出流,您可以直接写入文件描述符或通过使用 OutputStream 创建自己的 Socket 实现,这将覆盖刷新方法(例如,在 c 中使用Berkeley 套接字实现(通过本机调用)。