【问题标题】:Workaround java.io.EOFException cause by ObjectInputStream [duplicate]由 ObjectInputStream 引起的解决方法 java.io.EOFException [重复]
【发布时间】:2017-01-13 08:34:58
【问题描述】:

对于我的应用程序,我想使用 Map 作为数据库。为了保存和加载地图,我使用以下两种方法将其写入/读取到 database.ser:

private synchronized void saveDB() {
    try {
        fileOut = new FileOutputStream(db);
        out = new ObjectOutputStream(fileOut);
        out.writeObject(accounts);
        fileOut.close();
        out.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

@SuppressWarnings("unchecked")
private void loadDB() {
    try {
        fileIn = new FileInputStream(db);
        in = new ObjectInputStream(fileIn); // that is where error is produced if fileIn is empty
        accounts = (Map<String, Client>) in.readObject();
        in.close();
        fileIn.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

我想在应用程序启动时加载到 Map,所以我在构造函数中调用方法如下:

protected DriveatorImpl() {
    accounts = new ConcurrentHashMap<String, Client>();
    db = new File("C:/Users/eduar/git/Multy-Threaded-Bank-System/Bank-Services/database.ser"); 
// also, any suggestions how can I make path to a file more flexible in case I want to run Server side of an app on different machine?
     if (!db.exists()) {
        try {
            db.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
     }
    loadDB(); // loads database when server start 
}

我知道是什么导致了错误,但我不知道我应该在设计中进行哪些更改以避免 ObjectInputStream 构造函数接收空流! 关于我可以做些什么不同的任何建议?

编辑:我想指出,在新的应用程序运行中 database.ser 是空的,因为还没有进入 Map 的条目。

谢谢!

【问题讨论】:

    标签: java oop objectinputstream eofexception


    【解决方案1】:

    摆脱file.exists()/file.createNewFile() 废话。它为您所做的只是掩盖了最初的FileNotFoundException 问题,并变成了一个完全可预测的EOFException,因为它试图围绕一个空流构建一个ObjectInputStream。处理原始问题。不要只是移动它,或者把它变成别的东西。

    【讨论】:

    • 当我阅读您对原始帖子的评论时,我现在明白了。这将是我需要的一个优雅的解决方案。谢谢。
    【解决方案2】:

    首先为什么会出现EOFExcpetion?

    1. 文件中没有内容或文件为空,您尝试读取文件。

    一些代码更改,它对我有用。

    @SuppressWarnings("unchecked")
    private void loadDB() {
        try {
            if (db.length() <= 0) {
                // if statement evaluates to true even if file doesn't exists
                saveDB(); // save to a file an empty map
                          // if file doesn't exist, it creates a new one 
                          // call loadDB inside constructor
    
            }
            FileInputStream fileIn = new FileInputStream(db);
            ObjectInputStream in = new ObjectInputStream(fileIn); // that is where error is produced if fileIn is empty
            in.readObject();
            in.close();
            fileIn.close();
            System.out.println(accounts);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    

    【讨论】:

    • 我无法确定#2 的头部或尾部,第二个要点同样毫无意义。您的“另一种方式”与您最初检查空虚的方式完全相同。
    • 我认为检查空文件并从方法返回正是我所需要的!我在方法中调用 saveDB(),我在 map 中放置或修改值,以确保在服务器崩溃时保存所有数据。我想我现在明白为什么在 loadDB() 之前在构造函数中调用 saveDB() 方法会起作用。它将一个空映射写入文件,但仍有一些字节通过流。唯一的问题是,如果我已经在 Map 中存储了一些值并将其保存到文件中,则类的后续实例化将用空映射覆盖文件,并且所有数据都将丢失。感谢您的帮助!
    • 不客气。请尽量避免@EJP 提到的重复问题。这将有助于避免混乱。谢谢。
    • 我不同意@EJP 的问题是重复的。最后一个问题是关于文件路径和未找到文件异常。在审查期间发现了另一个错误,该错误导致 EOFExcpetion 并且与传递给 ObjectInputStream 构造函数的空流有关。我认为这个问题需要个人关注。
    • @GarRudo 请勾选我为您的问题提交的答案,以便其他人可以看到,这解决了您的问题。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    相关资源
    最近更新 更多