2010-07-22 14 views
0

J'ai une méthode qui utilise un binaire pour écrire un enregistrement composé de quelques uints et un tableau d'octets dans un fichier. Cette méthode s'exécute environ une douzaine de fois par seconde dans le cadre de mon programme. Le code est ci-dessous:binarywriter ne pas ouvrir le fichier à la fin du flux

iLogFileMutex.WaitOne(); 
using (BinaryWriter iBinaryWriter = new BinaryWriter(File.Open(iMainLogFilename, FileMode.OpenOrCreate, FileAccess.Write))) 
{ 
    iBinaryWriter.Seek(0, SeekOrigin.End); 
    foreach (ViewerRecord vR in aViewerRecords) 
    { 
     iBinaryWriter.Write(vR.Id); 
     iBinaryWriter.Write(vR.Timestamp); 
     iBinaryWriter.Write(vR.PayloadLength); 
     iBinaryWriter.Write(vR.Payload);   
    } 
}  
iLogFileMutex.ReleaseMutex(); 

Le code ci-dessus fonctionne très bien, mais si je retire la ligne à la recherche appel, le fichier binaire résultant est corrompu. Par exemple, certains enregistrements sont complètement absents ou des parties de ceux-ci ne sont tout simplement pas présents bien que la grande majorité des enregistrements soient écrits correctement. Donc, j'imagine que la cause du bug est quand j'ouvre et ferme le fichier à plusieurs reprises la position actuelle dans le fichier n'est pas toujours à la fin et les choses sont écrasées. Donc, ma question est la suivante: pourquoi C# n'assure-t-il pas que la position actuelle est à la fin lorsque j'ouvre le fichier?

PS: J'ai écarté les questions de filetage de causer ce bug

Répondre

1

Le problème est une combinaison de FileMode.OpenOrCreate et du type des membres ViewerRecord. Un ou plusieurs d'entre eux n'est pas de type à taille fixe, probablement une chaîne.

Les choses vont mal quand le fichier existe déjà. Vous commencerez à écrire des données au début du fichier, en écrasant les données existantes. Mais ce que vous écrivez écrase seulement un enregistrement existant par hasard, la chaîne devrait être exactement la même taille. Si vous n'écrivez pas assez d'enregistrements, vous n'écraserez pas tous les anciens enregistrements. Et avoir des ennuis lorsque vous lisez le fichier, vous lirez une partie d'un ancien enregistrement après avoir lu le dernier enregistrement écrit. Vous aurez de la camelote pendant un moment. Faire une taille fixe ne résout pas vraiment le problème, vous lirez un bon enregistrement mais ce sera un ancien. L'ensemble des anciens enregistrements dépend de la quantité de nouvelles données que vous avez écrites. Cela devrait être tout aussi mauvais que de lire des données brouillées.

Si vous avez vraiment besoin de conserver les anciens enregistrements, vous devez ajouter au fichier FileMode.Append. Si vous ne le faites pas, vous devez réécrire le fichier, FileMode.Create.

+0

Cela explique, acclamations :) – CalumMcCall

4

Si vous voulez ajouter au fichier, vous devez utiliser FileMode.APPEND dans votre appel ouvert, sinon le fichier sera ouvert avec sa position définie sur le début du fichier, pas la fin.

+0

Très vrai, j'aurais dû le signaler dans mon article. Cependant, pourquoi est-ce que je reçois encore beaucoup d'enregistrements, y compris le premier, écrit sans aucun problème, puis quelque part à mi-chemin dans le fichier, je reçois un demi-enregistrement et ensuite ceux qui le sont aussi. Ajouter, ou en manquer, ne le ferait pas? Sûrement je devrais seulement obtenir la dernière liste des disques écrits réellement présents dans le dossier? – CalumMcCall

+0

Est-ce que ce code n'est pas le code qui pose problème? –