2009-12-07 5 views
18

В большинстве операционных систем, совместимых с Unix и Posix, выполняющих вызов операционной системы open() с O_APPEND, указывается на ОС, которые записывают, должны быть атомарными добавлениями и записью. При таком поведении для локальных файловых систем при записи вы знаете, что они добавляются в конец файла.Как я могу выполнить атомарную запись/добавление в C# или как получить файлы, открытые с помощью флага FILE_APPEND_DATA?

Операционные системы Windows поддерживают ту же функциональность, передав FILE_APPEND_DATA в соответствующий параметр системному вызову Win32 CreateFile().

ссылки:

http://www.google.com/search?q=msdn+createfile 
or: http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx 

http://www.google.com/search?q=msdn+IoCreateFileSpecifyDeviceObjectHint 
or: http://www.google.com/search?q=msdn+IoCreateFileSpecifyDeviceObjectHint 

Моя проблема заключается в следующем, я не могу определить, как получить это поведение в C# с использованием библиотеки Net Framework, есть способ, чтобы получить такое поведение с помощью Net Framework? Я не верю, что использование FileMode.Append дает такое поведение, кстати.

ответ

30

Используйте один из перегрузок FileStream конструктора:

new FileStream(FileName, FileMode.Open, FileSystemRights.AppendData, 
      FileShare.Write, 4096, FileOptions.None) 

FileSystemRights.AppendData соответствует FILE_APPEND_DATA

FileStream кажется настаивать на буферизации, поэтому убедитесь, что буфер достаточно велик для каждого записи и вызова Flush() после каждого написать.

Крошечный пример:

private void button1_Click(object sender, EventArgs e) { 
     Thread t1 = new Thread(DoIt); 
     Thread t2 = new Thread(DoIt); 
     t1.Start("a"); 
     t2.Start("b"); 
     Thread.Sleep(2000); 
     Environment.Exit(0); 
    } 

    private void DoIt(object p) { 
     using (FileStream fs = new FileStream(FileName, FileMode.Open, FileSystemRights.AppendData, 
      FileShare.Write, 4096, FileOptions.None)) { 
      using (StreamWriter writer = new StreamWriter(fs)) { 
       writer.AutoFlush = true; 
       for (int i = 0; i < 20; ++i) 
        writer.WriteLine("{0}: {1:D3} {2:o} hello", p, i, DateTime.Now); 
      } 
     } 
    } 
+0

Фред, это замечательный ответ. – Cameron

+0

Точно так же, как с использованием API 'File.AppendText'? – Ben

+0

Последний параметр конструктора FileStream «bufferSize» или 4096 в этом примере будет верхней границей длины атомной записи. – Cameron

-1

Почему вы не можете использовать

System.IO.File.AppendAllText("C:\\somefile.txt", "some content"); 

? Это поточно-безопасный/«атомный» вызов.

+5

Это несчастливо не дает процесс мудрый атомарной операции я ищу. – Cameron

+0

Выдает IOException с помощью файла, который используется другим процессом, когда несколько потоков обращаются к файлу. – IvanH

1

Вы можете позвонить по номеру CreateFile с использованием PInvoke с требуемыми параметрами и передать результирующий дескриптор одному из FileStream Constructors, который берет SafeFileHandle в качестве параметра.

 Смежные вопросы

  • Нет связанных вопросов^_^