Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

Потеря данных при записи файла File.WriteAllLines

#c_sharp


Есть файл, в котором находятся данные data1, полное имя с адресом в переменной FullFileName.
Я записываю новые данные в данный файл File.WriteAllLines(FullFileName, data2);
Если во время выполнения записи произойдет ошибка, ну к примеру закончилось место
на носителе, то что произойдет? Файл будет пустой, в нем останутся данные data1, или
часть данных data2?
    


Ответы

Ответ 1



Файл будет пустой, в нем останутся данные data1, или часть данных data2? Вообще, из-за ошибки записи может произойти и то, и другое и третье: Если файл не получится открыть, то содержимое не изменится. Если файл получится открыть и затереть, но при этом при первой записи произойдет ошибка — файл будет пустой. Если запись оборвется посередине, то в файле останется часть новых данных. Если ошибка возникнет именно из-за нехватки места на носителе, то наиболее вероятен последний вариант, т.к. метод начнет записывать данные в файл, просто не сможет закончить. Вот пример кода, который симулирует все три варианта развития событий: 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; } } Он выводит: Unchanged: initial Empty: Partial: new line Если нужна защита от ошибок при записи файла, т.е. чтобы было два варианта: либо файл записался полностью, либо не изменился, то попробуйте записать данные во временный файл, и поменять файлы местами. При этом все равно сохраняется возможность возникновения ошибок, но по крайней мере есть вариант для отката и исключается сценарий с частичной записью данных. Посмотрите How to do atomic writes in a file.

Комментариев нет:

Отправить комментарий