Perte de puissance après que StreamWriter.Close () produise un fichier vide, pourquoi?

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

  •  07-07-2019
  •  | 
  •  

Question

Ok, donc à expliquer; Je développe pour un système qui peut subir une panne de courant à tout moment. Un des points que je teste est directement après la création d'un fichier à l'aide d'un StreamWriter. Le code ci-dessous:

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

Écrit le contenu de shellConfigWriter (une liste de chaînes) dans un fichier utilisé comme stockage temporaire, puis il est copié sur l'original. Désormais, une fois que ce code est terminé, le courant est perdu, lors de la sauvegarde, le fichier Game.cfg existe et sa taille est correcte, mais il est complètement vide. Au début, je pensais que cela était dû au fait que la mise en cache en écriture était activée sur le disque dur, mais même si elle était désactivée, cela se produisait quand même (mais moins souvent).

Toutes les idées seraient les bienvenues!

Mise à jour: OK, donc, après avoir supprimé les instructions .Close () et appelé .Flush () après chaque opération d'écriture, les fichiers finir en blanc. Je pourrais aller un peu plus loin et créer d’abord une sauvegarde du fichier d’origine, avant de créer le nouveau, puis j’ai assez de sauvegardes pour effectuer un contrôle d’intégrité, mais je ne pense pas que cela puisse aider à résoudre le problème sous-jacent ( que lorsque je lui dis d'écrire, vider et fermer un fichier ... Ce n'est pas le cas!).

Était-ce utile?

La solution

Empêchez le système d'exploitation de mettre en mémoire tampon la sortie à l'aide du paramètre FileOptions du constructeur de l'objet 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();
    }

Autres conseils

Tout d'abord, vous n'avez pas à appeler shellConfigWriter.Close () à cet endroit. L'instruction using s'en chargera. Pour vous prémunir contre les pannes de courant, appelez shellConfigWriter.Flush () .

Mettre à jour
Une autre chose à considérer est que, si une panne de courant peut survenir à n'importe quel , cela pourrait se produire au milieu d'une écriture, de sorte que seuls certains octets parviennent à un fichier. Il n'y a vraiment aucun moyen d'arrêter cela.

Pour vous protéger contre ces scénarios, une procédure courante consiste à utiliser des fichiers d'indicateur d'état / de condition. Vous utilisez l'existence ou la non-existence sur le système de fichiers d'un fichier de zéro octet avec un nom particulier pour indiquer à votre programme où il doit être récupéré lorsqu'il reprendra. Ensuite, vous ne créez ni ne détruisez les fichiers qui déclenchent un état particulier tant que vous n'êtes pas sûr d'avoir atteint cet état et d'avoir terminé le précédent.

L’inconvénient est que cela pourrait signifier de jeter beaucoup de travail de temps en temps. Mais l’avantage, c’est que la partie fonctionnelle de votre code a l’air normal: il reste très peu de travail supplémentaire à faire pour rendre le système suffisamment robuste.

Vous souhaitez définir AutoFlush = true;

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top