这些方法如何允许/导致磁盘上的数据丢失? [英] How are these methods allowing / causing data to be lost on disk?

查看:137
本文介绍了这些方法如何允许/导致磁盘上的数据丢失?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,它每隔一段时间(大约15秒)将其设置和数据写出到磁盘上.

I have a program that writes its settings and data out to disk every so often (15 seconds or so).

如果程序正在运行并且计算机突然关闭(例如,在墙壁上断电了),那么我磁盘上的所有数据文件都会以某种方式更改为空文件.

If the program is running and the computer is shut off abruptly -- for example, with the power being cut at the wall -- somehow all of my data files on disk are changed to empty files.

这是我的代码,我认为我是为了防止这种故障而设计的,但是基于测试,该故障仍然存在:

Here is my code, which I thought I designed to protect against this failure, but based on testing the failure still exists:

SaveAllData -经常调用一次,并且在调用JavaFX.Application.stop()时也是如此.

SaveAllData -- Called every so often, and also when JavaFX.Application.stop() is called.

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存储库在存在此问题的地方提交.参见Persister.java.

就像我说的那样,突然断电时,用此方法保存的所有设置文件都会被清空.这对我来说尤其没有意义,因为它们是按顺序调用的,并且我确保在调用move()之前将文件写入磁盘并进行刷新.

As I said, when the power is cut abruptly all setting files saved by this method are blanked. This makes particularly no sense to me, since they are called in sequence and I am making sure the file is written to disk and flushed before calling move().

任何想法这怎么可能发生?我认为通过调用冲洗,关闭然后移动,我可以确保在覆盖旧数据之前将数据写入磁盘.不知何故,事实并非如此,但我一无所知.有什么建议?

Any idea how this could be happening? I thought by calling flush, close, then move, I would ensure that the data is written to disk before overwriting the old data. Somehow, this isn't the case, but I am clueless. Any suggestions?

注意:这些文件仅由这些函数写入 ,而由相应的load()函数仅读取 .在程序中的其他任何地方都没有其他访问文件的权限.

Note: these files are only written to by these functions, and only read from by corresponding load() functions. There is no other access to the files any where else in my program.

注2:我正在Ubuntu Linux 16.10上遇到此问题.我尚未在其他平台上对其进行测试.

Note 2: I am experiencing this on Ubuntu Linux 16.10. I have not tested it on other platforms yet.

推荐答案

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

Adding StandardCopyOption.ATOMIC_MOVE to the Files.move() call solves the problem:

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." );
    }
}

这篇关于这些方法如何允许/导致磁盘上的数据丢失?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆