Come posso fare una scrittura atomica / accodare in C #, o come faccio a ottenere i file aperti con la bandiera FILE_APPEND_DATA?
Domanda
In molti Unix e Posix conformi sistemi operativi che eseguono un () chiamata di sistema operativo aperto con l'O_APPEND indica al sistema operativo che scrive devono essere accodamento atomico e scrittura. Con questo comportamento, per i file system locali quando si esegue una scrittura, si sa che ottiene aggiunto alla fine del file.
I sistemi operativi Windows supportano la stessa funzionalità passando FILE_APPEND_DATA
nel parametro appropriato per Win32 CreateFile) chiamata di sistema (.
riferimenti:
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
Il mio problema è questo, non posso determinare come ottenere questo comportamento in C # utilizzando il Net Framework Biblioteche, c'è un modo per ottenere tale comportamento con il Net Framework? Non credo usando FileMode.APPEND dà tale comportamento, tra l'altro.
Soluzione
Utilizzare uno degli overload del costruttore FileStream
:
new FileStream(FileName, FileMode.Open, FileSystemRights.AppendData,
FileShare.Write, 4096, FileOptions.None)
FileSystemRights.AppendData
corrisponde FILE_APPEND_DATA
FileStream sembra insistere sul buffer, in modo da assicurarsi il buffer è abbastanza grande per ogni
scrivere e chiamare Flush()
dopo ogni scrittura.
piccolo esempio:
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);
}
}
}
Altri suggerimenti
È possibile chiamare CreateFile usando < a href = "http://www.pinvoke.net/default.aspx/kernel32/CreateFile.html" rel = "nofollow"> PInvoke con i parametri richiesti e passare la maniglia conseguente ad uno dei FileStream Costruttori che prende SafeFileHandle come parametro.
Perché non si può usare
System.IO.File.AppendAllText("C:\\somefile.txt", "some content");
? Questo è un thread-safe / "atomica" chiamata pure.