这些方法如何允许/导致数据在磁盘上丢失?

时间:2017-11-05 20:46:32

标签: java persistence

我有一个程序,每隔一段时间(15秒左右)将其设置和数据写入磁盘。

如果程序正在运行且计算机突然关闭 - 例如,电源被切断 - 不知何故,磁盘上的所有数据文件都将更改为空文件。

这是我的代码,我认为我的目的是为了防止此故障,但基于测试,故障仍然存在:

SaveAllData - 经常调用,也调用JavaFX.Application.stop()。

public void saveAllData () {
    createNecessaryFolders();
    saveAlbumsAndTracks();
    saveSources();
    saveCurrentList();
    saveQueue();
    saveHistory();
    saveLibraryPlaylists();
    saveSettings();
    saveHotkeys();
}

CreateNecessaryFolders

private void createNecessaryFolders () {
    if ( !playlistsDirectory.exists() ) {
        boolean playlistDir = playlistsDirectory.mkdirs();
    }
}

保存功能 - 它们看起来都像这样

public void saveCurrentList () {
    File tempCurrentFile = new File ( currentFile.toString() + ".temp" );
    try ( ObjectOutputStream currentListOut = new ObjectOutputStream( new FileOutputStream( tempCurrentFile ) ) ) {
        currentListOut.writeObject( player.getCurrentList().getState() );
        currentListOut.flush();
        currentListOut.close();

        Files.move( tempCurrentFile.toPath(), currentFile.toPath(), StandardCopyOption.REPLACE_EXISTING );

    } catch ( Exception e ) {
        LOGGER.warning( e.getClass().getCanonicalName() + ": Unable to save current list to disk, continuing." );
    }
}

Github repository to commit where this problem exists. See Persister.java.

正如我所说,当电源突然切断时此方法保存的所有设置文件都会被消隐。这对我来说特别没意义,因为它们是按顺序调用的,我确保在调用move()之前将文件写入磁盘并刷新。

知道如何发生这种情况吗?我想通过调用flush,close,然后移动,我会确保在覆盖旧数据之前将数据写入磁盘。不知何故,事实并非如此,但我一无所知。有什么建议?

注意:这些文件仅 写入这些文件,从相应的load()函数读取。在我的程序中的任何其他位置都没有其他文件访问权限。

注意2:我在Ubuntu Linux 16.10上遇到过这种情况。我还没有在其他平台上测试它。

1 个答案:

答案 0 :(得分:0)

StandardCopyOption.ATOMIC_MOVE添加到Files.move()调用可以解决问题:

public void saveCurrentList () {
    File tempCurrentFile = new File ( currentFile.toString() + ".temp" );
    try ( ObjectOutputStream currentListOut = new ObjectOutputStream( new FileOutputStream( tempCurrentFile ) ) ) {
        currentListOut.writeObject( player.getCurrentList().getState() );
        currentListOut.flush();
        currentListOut.close();

        Files.move( tempCurrentFile.toPath(), currentFile.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE );

    } catch ( Exception e ) {
        LOGGER.warning( e.getClass().getCanonicalName() + ": Unable to save current list to disk, continuing." );
    }
}