Действительно единственный «безопасный» способ сделать это - полагаться на основную файловую систему.
Просто:
public void saveThing(Serializable thing, String fileName) throws Exception {
String tempFileName = fileName + "_tmp";
File tempFile = new File(tempFileName);
FileOutputStream fos = new FileOutputStream(tempFile);
FileDescriptor fd = fos.getFD();
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(thing);
oos.flush();
fd.sync();
oos.close();
f.renameTo(fileName);
}
То, что здесь происходит, первое, что мы пишем файл во временный файл. Это гарантирует, что вся запись файла будет успешной, не повреждая исходный файл (например, если у вас закончится дисковое пространство, оригинал будет сохранен, так как эта процедура не будет завершена). Однако, если эта процедура выходит из строя, сохраняющийся временный файл останется, и его нужно будет очистить позже.
После того, как мы написали файл, мы вынуждаем ОС сбрасывать любые ожидающие записи на фактический диск. Многие системные файловые системы записывают в RAM, и «в конечном итоге» записывают их на диск.Это связано с очевидными показателями производительности. Однако, если система выйдет из строя или потеряет питание между вами, когда вы закрыли файл, и ОС решит сбросить записи, вы можете потерять данные. Эта синхронизация является ДОРОЖНОЙ операцией.
Наконец, как только мы уверены, что мы написали файл и что он привязан к диску (насколько это возможно, так или иначе), мы затем RENAME создаем файл temp для фактического имени файла.
Переименование файла в файловой системе является атомной операцией. Это не может частично потерпеть неудачу. Это либо работает, либо нет. Если два файла находятся в одной и той же файловой системе, переименование почти мгновенно, так как оно просто обновляет некоторую информацию о файловой системе. Если эти два находятся в отдельных файловых системах, то новый файл сначала необходимо скопировать в новую файловую систему, а затем переименовать. Я ПРИНИМАЮ, что это так, я никогда не тестировал это. Я склонен придерживаться той же файловой системы и полностью избегаю вопроса.
Этот процесс гарантирует, что файл будет обновлен под правильным именем, полностью, «все сразу». Файл (под его правильным именем) не только «частично существует», что и произойдет, если вы просто перезапишете существующий файл.
И наконец, в Windows может возникнуть проблема, если есть конфликт для исходного файла, поскольку Windows не удалит файл, который открывается чем-то другим. Unix не имеет никаких проблем с этим, но Windows делает это. Поэтому перед выполнением этой процедуры переименования вам необходимо убедиться, что у вас есть единственный доступ к файлу.
Этот адский ответ! Большое спасибо! – Queequeg