【问题标题】:When to use flush() in java?什么时候在java中使用flush()?
【发布时间】:2011-11-10 04:04:15
【问题描述】:
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 ; )
  • 你所说的“携带乐谱”是什么意思?

标签: java serialization


【解决方案1】:
  1. 什么时候使用flush方法,为什么要使用它?

这个在需要同步发送的时候使用

例如,您有一个双工(2 路)连接并且您刚刚发送了一条消息,现在需要等待它的回复,如果不刷新缓冲的输出流可能会保持它直到缓冲区填满(死锁)

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

错了!您从流中读取一些数据,将其类型转换为 John(如果读取的对象不是 John,则会抛出)

  1. 在 Java 中序列化或持久化数据的替代方法是什么。我不希望数据作为字节流进入文件。

您可以将其写为文本(将字段写为一行上的文本)并提供将其解析为对象的方法

【讨论】:

    【解决方案2】:

    什么时候使用flush方法,为什么要使用它?

    它会刷新仍由OutputStream 缓冲的任何内容。详细说明见JavaDoc。


    close方法在这里带什么分数?

    我不确定您所说的“评分”是什么意思,但 close 方法最终会关闭资源(输入或输出),它会释放例如文件句柄。您应该始终在 finally 块中调用 close 以清除操作系统可能拥有的所有引用。

    InputStream is = null;
    try {
        is = new FileInputStream(...);
        // do stuff
    } catch (IOException e) {
        // do stuff
    } finally {
        if (is != null) {
            is.close();
        }
    }
    

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

    不知何故正确,您反序列化了之前写入文件的对象。这些文件是专有的,只能被 Java 理解,所以你的最后一个问题是一个好!


    序列化或将数据持久化的替代方法是什么 爪哇。我不希望数据作为字节流进入文件。

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

    【讨论】:

      【解决方案3】:

      对上面的例子有几个问题。

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

        你通常不需要flush()和OutputStream,如果你正确地close()最后它不会丢失任何数据。有时,您希望与底层数据接收器(例如网络Socket、本地File 或另一个OutputStream)通信,您希望写入流的任何数据都被刷新/处理——但根据@ 987654321@ 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 中序列化或持久化数据的替代方案是什么。我不希望数据作为字节流进入文件。

        您可以研究其他序列化/编组方法,例如 XStream、JSON 或自行开发(很复杂,只有在您有充分理由的情况下才这样做)。其中大部分将被证明比内置序列化更复杂,因此请确保您有充分的理由不只是将“itno 文件作为字节流”编写。

      【讨论】:

      • 你确定(2)是正确的吗? close() 的 API 在哪里保证所有未完成的字节都将被刷新?
      • 文档很少,主要是个人经验——大多数流会在关闭它们时flush(),比如大多数其他扩展的FilterOutputStream和ObjectOutputStream,它们都尽职尽责地实现flush(),使用尤其是GZIPOutputStream 的例外。
      • @PaulGrime 见FilterOutputStream.close()。
      【解决方案4】:
      1. 您使用 flush() 来清除内部缓冲区(如果有)并强制将所有待处理的数据写入(即刷新)到流目的地。
      2. close() 方法用于关闭流,一旦调用,就不能再使用流了。
      3. 否。您正在阅读“文件中的 John 对象”。 John 类型的对象之前应该已经序列化到文件中。
      4. Java 序列化有许多替代方案,例如XStream。请参阅alternatives to serialization 的这个 SO 答案。

      【讨论】:

        【解决方案5】:

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

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

        3) 您没有读取文件对象。您正在从文件中读取先前序列化的 Java 对象。希望这个对象是 John 类型,否则你会得到一个 ClassCastException。它将是 John 类型,正如您之前所说的“oos.writeObject(myObj)”,其中 myObj 是 John 类型。

        4) 用于序列化 Java 对象的 Google。用于将 Java 对象序列化为二进制文件、xml、json 等的库有很多。JDK 本身带有一个称为 XMLEncoder 的库。

        【讨论】:

          【解决方案6】:
          1. 何时使用冲洗:

          flush函数就是明确要求Java程序往磁盘中写入东西,也就是做IO。假设我们使用的是 bufferedOutputStream,当我们执行 write("something") 时,它存储在缓冲区中,但还没有存储在磁盘中。当您调用flush时,它会将缓冲区中的内容写入磁盘。通常,你不需要自己调用flush,因为它需要IO并且降低了速度。当缓冲区已满时,流将自动刷新。除非您希望将某些内容更新到磁盘,否则可以使用刷新。

          1. 抱歉,不明白您的问题?哪个分数?

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

          3. 有很多方法(xml、数据库、txt 文件),编写自己的格式将数据存储在本地文件中,或者将它们存储在数据库中。让我在这里用你的例子约翰。它具有名称和部门属性。您可以编写一个采用 John 实例的格式输出,然后执行以下操作。

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-12-02
            • 2012-03-11
            • 2016-07-27
            • 2012-07-29
            • 2016-12-24
            • 2011-05-06
            • 2014-01-28
            相关资源
            最近更新 更多