Perda de poder após StreamWriter.Close () produz um arquivo em branco, por quê?

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

  •  07-07-2019
  •  | 
  •  

Pergunta

Ok, então a explicar; Estou desenvolvendo um sistema que pode sofrer uma falha de energia em qualquer ponto no tempo, um ponto que eu estou testando é diretamente depois de eu ter escrito um arquivo usando um StreamWriter. O código a seguir:

// Write the updated file back out to the Shell directory.
using (StreamWriter shellConfigWriter =
        new StreamWriter(@"D:\xxx\Shell\Config\Game.cfg.bak"))
{
    for (int i = 0; i < configContents.Count; i++)
    {
        shellConfigWriter.WriteLine(configContents[i]);
    }
    shellConfigWriter.Close();
}

FileInfo gameCfgBackup = new FileInfo(@"D:\xxx\Shell\Config\Game.cfg.bak");
gameCfgBackup.CopyTo(@"D:\xxx\Shell\Config\Game.cfg", true);

Grava o conteúdo do shellConfigWriter (a List de cordas) para um arquivo usado como um armazenamento temporário, em seguida, ele é copiado sobre o original. Agora, depois de este código terminar a execução da energia é perdida, assim que iniciar novamente para cima o Game.cfg arquivo existe e é o tamanho correto, mas é completamente em branco. No começo eu pensei que este era devido ao cache de gravação a ser habilitado no disco rígido, mas mesmo com ele desligado ainda ocorre (embora com menos frequência).

Todas as idéias seriam muito bem-vindos!

Update: Ok, então depois de remover as declarações .Close() e chamando .Flush() depois de cada operação de gravação dos arquivos ainda acabar em branco. Eu poderia ir um passo além e criar um backup do arquivo original em primeiro lugar, antes de criar o novo, e então eu tenho backups suficientes para fazer uma verificação de integridade, mas eu não acho que ele vai ajudar a resolver o problema subjacente ( que quando eu dizer-lhe para escrever para, lave e fechar um arquivo ... ele não!).

Foi útil?

Solução

Mantenha o sistema operacional a partir de buffer a saída usando o parâmetro FileOptions do construtor do objeto FileStream:

    using (Stream fs = new FileStream(@"D:\xxx\Shell\Config\Game.cfg.bak", FileMode.Create, FileAccess.Write, FileShare.None, 0x1000, FileOptions.WriteThrough))
    using (StreamWriter shellConfigWriter = new StreamWriter(fs))
    {
        for (int i = 0; i < configContents.Count; i++)
        {
            shellConfigWriter.WriteLine(configContents[i]);
        }
        shellConfigWriter.Flush();
        shellConfigWriter.BaseStream.Flush();
    }

Outras dicas

Em primeiro lugar, você não tem que shellConfigWriter.Close() chamada lá. A declaração using vai cuidar dela. O que você pode querer fazer, em vez de se proteger contra falha de energia é chamada shellConfigWriter.Flush().


Atualizar
Outra coisa que você pode querer considerar é que, se uma falha de energia pode realmente acontecer em qualquer tempo, isso poderia acontecer no meio de uma gravação, de modo que apenas alguns dos bytes torná-lo em um arquivo. Não há realmente nenhuma maneira de parar isso.

Para se proteger contra esses cenários, um procedimento comum é usar arquivos da bandeira do estado / condição. Você usa a existência ou não existência no sistema de um arquivo de zero-byte arquivo com um nome específico para dizer ao seu programa onde para pegar novamente quando ele retoma. Então você não criar ou destruir os arquivos que desencadeiam um estado particular até que você esteja certeza que você alcançou aquele estado e completou o anterior.

A desvantagem é que ele pode significar jogando um monte de trabalho fora agora e então. Mas a vantagem é que isso significa que a parte funcional de sua aparência código como normal:. Há um trabalho muito pouco mais para fazer para tornar o sistema suficientemente robusto

Você deseja definir AutoFlush = true;

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