using System;
using System.IO;
using System.Linq;
using System.Threading;
class Program
{
static void Main()
{
//записываем три файла с одинаковым текстом
File.WriteAllText("unchanged", "initial");
File.WriteAllText("empty", "initial");
File.WriteAllText("partial", "initial");
//симулируем ошибки
//один файл занимаем другим потоком (в реальности может быть другой процесс)
//запись оборвется при попытке открытия
var unchangedLock = new FileStream("unchanged", FileMode.Open);
//в другом блокируем часть файла
//запись оборвется при попытке записи
var emptyLock = new FileStream("empty", FileMode.Open,FileAccess.Read, FileShare.ReadWrite);
emptyLock.Lock(1, 1);
//запускаем потоки для перезаписи файлов
var unchangedThread = CreateWriteThread("unchanged");
var emptyThread = CreateWriteThread("empty");
var partialThread = CreateWriteThread("partial");
//дожидаемся завершения записи
unchangedThread.Join();
emptyThread.Join();
//запись третьего файла обрывается посередине
//по каким-то причинам, например, из-за нехватки места на диске
partialThread.Abort();
//освобождаем файлы чтобы прочитать
unchangedLock.Close();
emptyLock.Close();
//выводим первые строки после записи
//первый файл не изменился
Console.WriteLine("Unchanged: " + File.ReadLines("unchanged").FirstOrDefault());
//второй стал пустым
Console.WriteLine("Empty: " + File.ReadLines("empty").FirstOrDefault());
//третий перезаписан, но не до конца
Console.WriteLine("Partial: " + File.ReadLines("partial").FirstOrDefault());
Console.Read();
}
static Thread CreateWriteThread(string filename)
{
var thread = new Thread(() =>
{
try
{
File.WriteAllLines(filename, Enumerable.Repeat("new line", 1000000));
}
catch{/*nobody cares*/}
});
thread.Start();
return thread;
}
}
一般来说,由于一个写入错误,一个和另一个和第三个都可能发生:
如果错误的发生正是因为媒体空间不足,那么很可能是最后一个选项,因为。该方法将开始将数据写入文件,但无法完成。
这是一个模拟所有三种场景的代码示例:
它输出:
如果您在写入文件时需要防止错误,即 所以有两个选择:要么文件被完全写入,要么它没有改变,然后尝试将数据写入临时文件并交换文件。这仍然保留了出错的可能性,但至少有一个回滚选项,并消除了部分数据记录的情况。请参阅如何在文件中进行原子写入。