Como posso fazer uma gravação atômica / append em C #, ou como faço para obter arquivos abertos com a bandeira FILE_APPEND_DATA?

StackOverflow https://stackoverflow.com/questions/1862309

  •  16-09-2019
  •  | 
  •  

Pergunta

De acordo com a maioria dos sistemas operacionais em conformidade unixes e POSIX executar uma () chamada de sistema aberto operando com o O_APPEND indica para o sistema operacional que as gravações são para ser operações acrescentar e gravação atômicas. Com este comportamento, para sistemas de arquivos locais quando você faz uma gravação, você sabe que se acrescentado ao final do arquivo.

Os sistemas operacionais Windows suportam a mesma funcionalidade, passando FILE_APPEND_DATA no parâmetro adequado ao Win32 CreateFile () chamada de sistema.

referências:

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

O meu problema é o seguinte, eu não posso determinar como obter esse comportamento em C # usando o Net Framework Bibliotecas, há uma maneira de obter esse tipo de comportamento usando a Net Framework? Eu não acredito usando FileMode.APPEND dá esse tipo de comportamento, pelo caminho.

Foi útil?

Solução

Use uma das sobrecargas do construtor FileStream:

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

FileSystemRights.AppendData corresponde com FILE_APPEND_DATA

FileStream parece insistir em buffer, por isso certifique-se o buffer é grande o suficiente para cada gravação e chamada Flush() depois de cada gravação.

exemplo minúsculo:

    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);
            }
        }
    }

Outras dicas

Você pode chamar CreateFile usando < a href = "http://www.pinvoke.net/default.aspx/kernel32/CreateFile.html" rel = "nofollow"> PInvoke com os parâmetros necessários e passar o identificador resultante para um dos FileStream Construtores que leva SafeFileHandle como parâmetro.

Por que você não pode usar

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

? Isso é um / call "atômica" thread-safe bem.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top