Ответ 1
Под Windows просмотрите FlushFileBuffers (API Win32).
Я понимаю, что метод .NET FileStream Flush записывает только текущий буфер на диск, но зависит от драйвера диска Windows и прошивки жесткого диска. Это не гарантирует, что данные фактически физически записаны на диск.
Есть ли способ .NET или Win32, который может дать мне эту гарантию? Итак, если есть потеря мощности на одну наносекунду после того, как вызов этого метода вернется, я все еще могу быть уверен, что все в порядке?
Под Windows просмотрите FlushFileBuffers (API Win32).
Стефан С. сказал:
Я понимаю, что метод .NET FileStream Flush только записывает текущий буфер на диск
Нет,.NET FileStream Flush только записывает буферы .NET в кэш OS, он не очищает кеш OS на диске. К сожалению, документ MSDN этого класса не говорит об этом. Для .NET < 4.0, вам нужно будет вызвать Flush + Win32 FlushFilebuffers:
using System.Runtime.InteropServices;
. . .
// start of class:
[DllImport("kernel32", SetLastError=true)]
private static extern bool FlushFileBuffers(IntPtr handle);
. . .
stream.Flush(); // Flush .NET buffers to OS file cache.
#pragma warning disable 618,612 // disable stream.Handle deprecation warning.
if (!FlushFileBuffers(stream.Handle)) // Flush OS file cache to disk.
#pragma warning restore 618,612
{
Int32 err = Marshal.GetLastWin32Error();
throw new Win32Exception(err, "Win32 FlushFileBuffers returned error for " + stream.Name);
}
Для .NET 4.0 вместо этого вы можете использовать новый метод flush (true). 11/09/2012 обновление: отчет об ошибке MS здесь говорит, что он сломан, а затем исправлен, но не говорит, какая версия или пакет обновления исправлены в! Звучит как ошибка, если внутренний буфер .NET FileStream пуст, Flush (true) ничего не сделал??
Ну, вы можете закрыть файл... это, вероятно, сделает это. В действительности, с абстракцией HAL, виртуализацией и дисковым оборудованием, имеющим больше вычислительной мощности и кэш-памяти, чем компьютеры, которые были сделаны несколько лет назад, вам придется жить, надеясь, что диск выполнит свою работу.
Транзакционная файловая система никогда не была материализована;-p Конечно, вы могли бы взглянуть на использование базы данных в качестве задней части и использовать транзакционную систему?
Кроме того: обратите внимание, что не все потоки даже гарантируют Flush()
- например, GZipStream
и т.д. сохраняют рабочий буфер нефиксированных данных даже после флеша - единственный способ заставить его сбросить все на Close()
он.
Я заметил, что .NET 4 #Flush (true) на самом деле не записывает на диск. У нас были странные проблемы с поврежденными данными, и я нашел этот на сайте MS:
На вкладке "Сведения" для отчета об ошибке есть тестовая программа, которую вы можете запустить, которая покажет проблему;
fs.Flush(true)
. Это не требует времени (гораздо быстрее, чем может быть записано на диск).FlushFileBuffers
. Это занимает много времени.Я перехожу к вызову win32 FlushFileBuffers...
Данные файла, которые буферизуются в кеше файловой системы, записываются на диск. Эти данные обычно лениво записываются в зависимости от положения головки записи на диске. Наличие гигабайта кэшированных данных технически возможно, так что это может занять некоторое время. Если это важно для вас, тогда рассмотрите опцию FileOptions.WriteThrough
.
Существует простой ответ на сброс содержимого буфера на диск. После функции WriteAllText откройте файл, закройте его и сбросьте его
вот пример
My.Computer.FileSystem.WriteAllText(yourfilename, "hello", False, System.Text.Encoding.ASCII)
FileOpen(1, yourfilename, OpenMode.Input)
FileClose(1)
Reset()
Просто слишком много уровней абстракции, чтобы быть абсолютно уверенными, что данные записываются на диск, вплоть до уровня аппаратного обеспечения.
Не блестяще исполняемый или надежный, но как насчет повторного открытия файла после его написания в отдельном процессе и проверки размера или содержимого?