在Java中什么时候需要使用flush()函数?

6
import java.io. * ;
public class Ser {

    public static void main(String args[]) {

        try {
            John myObj = new John("Sachin", "Cricket");
            System.out.println(myObj);
            FileOutputStream fos = new FileOutputStream("FileName");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(myObj);
            oos.flush();
            oos.close();
        } catch (Exception e) {
            System.out.println("Expection" + e);
            System.exit(0);
        }

        try {
            John myObj2;
            FileInputStream fis = new FileInputStream("FileName");
            ObjectInputStream ois = new ObjectInputStream(fis);
            myObj2 = (John) ois.readObject();
            ois.close();
            System.out.println("New Object" + myObj2);
        } catch (Exception e) {
            System.out.println("Expection" + e);
            System.exit(0);
        }

    }
}

class John implements Serializable {

    private String name;
    private String department;

    public John(String name, String department) {
        this.name = name;
        this.department = department;
    }

    public String toString() {
        return "Name" + name + " " + "Department" + department;

    }

}

我有几个问题需要解答:

  1. 什么时候使用flush方法?为什么要使用它?
  2. 在这里,close方法有什么作用?
  3. myObj2 = (John) ois.readObject(); ... 请纠正我如果我错了,我正在读取文件对象并将其存储到另一个对象中并进行类型转换。
  4. Java中序列化或持久化数据的替代方案有哪些?我不希望数据以字节流形式存储到文件中。

@John Cooper:我用它来解决BufferedImage的泄漏问题(即使没有对其引用,未刷新的图像也不会被收集)。哦,等等……那个flush;) - SyntaxT3rr0r
“carry a score” 是什么意思? - user207421
6个回答

10
  1. 何时使用flush方法?为什么要使用它?

在需要同步发送数据的情况下使用该方法。例如,当您有一种双工(双向)连接且刚刚发送了一条消息,并且现在需要等待其回复时,如果没有使用flush,则缓冲输出流可能会将其保留直到缓冲区填满(死锁)。

  1. myObj2 = (John) ois.readObject();请纠正我,如果我错了,我正在读取文件对象并将其存储到另一个对象中,并进行类型转换。

错误!您从流中读取了一些数据,将其强制转换为John(如果读取的对象不是John,则会引发异常)。

  1. Java中序列化或持久化数据的替代方法有哪些?我不想将数据作为字节流写入文件中。

您可以将其写成文本(将字段作为一行文本输出),并提供一种将文本解析为对象的方法。


7

何时使用flush方法以及为什么要使用它?

它会清空由OutputStream缓冲的任何内容。详细描述可在JavaDoc中找到。


“carry a score”在这里是什么意思?我不确定,但是close方法最终会关闭资源(输入或输出),释放例如文件句柄等。您应该始终在finally块中调用close以清理操作系统可能拥有的所有引用。
InputStream is = null;
try {
    is = new FileInputStream(...);
    // do stuff
} catch (IOException e) {
    // do stuff
} finally {
    if (is != null) {
        is.close();
    }
}

myObj2 = (John) ois.readObject(); ... 如果我错了,请纠正我,我正在读取文件对象并将其存储到另一个对象中,并进行类型转换。

有些正确,您在反序列化之前写入文件的对象。这些文件是专有的,只能由Java理解,因此您的最后一个问题是一个很好的问题!


Java中序列化或持久化数据的替代方案是什么?我不想将数据以字节流形式写入文件。

您有多种选择。对于客户端应用程序,您可以使用XML、JSON或像SQLlite这样的轻量级数据库。在服务器端,您可能还需要查看更强大的数据库(例如MySQL)。


4

在上面的例子中,我有几个问题。

  1. 何时使用flush方法,为什么要使用它?

    通常情况下,您不需要在OutputStream上调用flush(),只要您在最后正确地调用close(),就不会丢失任何数据。有时候,您希望向底层数据源(如网络Socket、本地File或另一个OutputStream)传达写入到流中的任何数据都被刷新/处理 - 但根据flush() API文档,这并不保证发生。

  2. 在这里,close方法扮演了什么角色?

    我真的不理解这部分,但是close()关闭一个OutputStream并导致它写出任何仍然具有缓冲的数据 - 因此在close()之前没有必要调用flush()OutputStream在关闭后不能再写入。

  3. myObj2 = (John) ois.readObject(); ...请纠正我如果我错了,我正在从文件对象中读取并存储到另一个对象中,并将文件对象强制转换。

    错了,您正在从ObjectInputStream ois中读取,它的数据源是无关紧要的(在您的代码中确实来自文件,但您的代码中没有“文件对象”)。

    ObjectInputStream可以重构以前由ObjectOutputStream编写/序列化的任何数据 - 因此在这种情况下,您反序列化先前序列化的John类型的对象。因为序列化仅适用于某些Java类型(基元和Serializable的实现者),它不知道您特定的类John。但是您知道,您先前已经序列化了一个John对象,因此可以安全地从Object转换为John并将其分配给本地变量。

  4. 什么是Java中序列化或持久化数据的替代方法。我不希望数据以字节流形式进入文件。

    您可以尝试其他序列化/编组方法,如XStreamJSON或自己编写(复杂,只有在您有充分理由的情况下才这样做)。其中大多数将比内置序列化更复杂,因此请确保您有充分的理由不仅仅是将数据“以字节流形式写入文件”。


1
你确定 (2) 是正确的吗?close() 的 API 在哪里保证所有未完成的字节都会被刷新? - Paul Grime
文档很少,大多数是个人经验--大多数流在关闭时都会flush(),例如FilterOutputStream,它是其他大多数流的扩展和ObjectOutputStream,它们都忠实地实现了flush(),但GZIPOutputStream是一个值得注意的例外。 - Philipp Reichart
@PaulGrime 请查看 FilterOutputStream.close() - user207421

2
  1. 您可以使用flush()方法清除内部缓冲区(如果有),并强制将所有待处理数据写入流目标。
  2. close()方法用于关闭流,一旦调用,就无法再使用该流。
  3. 不是。您正在从文件中读取“John对象”。类型为John的对象应该已经序列化到文件中。
  4. Java序列化有许多替代方案,例如XStream。请参阅此SO答案以获取序列化的替代方案

1

1) 确保写入任何可能的缓冲字节。请参阅java.io.OutputStream.flush()

2) 不确定您的意思,但是调用close()应该放在finally块中以确保资源已关闭。快速谷歌搜索结果 - article

3) 您没有读取文件对象。您正在从文件中读取先前序列化的Java对象。希望此对象将是John类型,否则您将收到ClassCastException。它将是John类型,因为您之前调用了“oos.writeObject(myObj)”,其中myObj是John类型。

4) 谷歌搜索Java对象序列化。有许多库可将Java对象序列化为二进制文件、xml、json等等。JDK本身带有一个称为XMLEncoder的库。


1
  1. 何时使用flush:

Flush函数是显式要求Java程序将某些内容写入磁盘,也就是进行IO操作。比如说,如果我们正在使用BufferedOutputStream,在执行write("something")时,它会被存储在缓冲区中,但尚未写入磁盘。当您调用flush时,它将把缓冲区中的内容写入磁盘。通常情况下,您不需要自己调用flush,因为它需要进行IO操作,会降低速度。只有当您想要更新某些内容到磁盘时,才需要使用flush。

  1. 抱歉,我不明白你的问题是关于哪个分数?

  2. 这就是序列化的作用,它允许你将某个对象存储到文件系统中并取回它。你正在读取字节流并将其转换回对象。

  3. 有很多方法(如xml、数据库、txt文件),可以编写自己的格式来将数据存储在本地文件中,或者将它们存储在数据库中。让我们以你的例子John为例。它有姓名和部门属性。你可以编写一个格式输出,接受一个John实例,并执行以下操作:

    outputStream.write("class John\n"); outputStream.write("toString: "+instance+"\n"); outputStream.close();

然后它将保存为本地txt文件,你可以打开它并阅读它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接