views:

41

answers:

2

Hi,

I have a method which uses a binarywriter to write a record consisting of few uints and a byte array to a file. This method executes about a dozen times a second as part of my program. The code is below:

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

The above code works fine, but if I remove the line with the seek call, the resulting binary file is corrupted. For example certain records are completely missing or parts of them are just not present although the vast majority of records are written just fine. So I imagine that the cause of the bug is when I repeatedly open and close the file the current position in the file isn't always at the end and things get overwritten.

So my question is: Why isn't C# ensuring that the current position is at the end when I open the file?

PS: I have ruled out threading issues from causing this bug

+4  A: 

If you want to append to the file, you must use FileMode.Append in your Open call, otherwise the file will open with its position set to the start of the file, not the end.

Will Dean
Very true, I should have pointed that out in my post. However, why do I still get loads of records, including the first one, written without any issues and then somewhere halfway through the file I get half a record written and then those after it are fine as well. Append, or lack therof, wouldn't cause that would it? Surely I should only get the last list of records written actually present in the file?
teflon19
So is that code you've posted not actually the code which is having the problem?
Will Dean
+1  A: 

The problem is a combination of FileMode.OpenOrCreate and the type of the ViewerRecord members. One or more of them isn't of a fixed size type, probably a string.

Things go wrong when the file already exists. You'll start writing data at the start of the file, overwriting existing data. But what you write only overwrites an existing record by chance, the string would have to be the exact same size. If you don't write enough records then you won't overwrite all of the old records. And get into trouble when you read the file, you'll read part of an old record after you've read the last written record. You'll get junk for a while.

Making the record a fixed size doesn't really solve the problem, you'll read a good record but it will be an old one. Which particular set of old records you'll get depends on how much new data you wrote. This should be just as bad as reading garbled data.

If you really do need to preserve the old records then you should append to the file, FileMode.Append. If you don't then you should rewrite the file, FileMode.Create.

Hans Passant
That explains it, cheers :)
teflon19