I found a strange problem with FileStream.SetLength(0). When writing first something to a stream and then calling SetLength(0), the content of the previous write still gets written to the file:
var fileName = "test.txt";
using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 8000, FileOptions.None))
{
using (var streamWriter = new StreamWriter(fileStream, Encoding.Default, bufferSize: 8000, leaveOpen: true))
{
streamWriter.WriteLine("123");
fileStream.SetLength(0);
streamWriter.WriteLine("abc");
}
}
var fileContent = File.ReadAllText(fileName);
fileContent becomes "123\\r\\nabc\\r\\n"
Obviously, 123 did not get deleted, even it was written before calling SetLength(0).
Using Seek() or setting the Position to 0 did not help.
In my application, I am writing to a file, which I keep open. From time to time it can happen that I need to empty the file completely and write a different content. For performance reasons, I don't want to close the streamWriter.
Note to all those guys who love to mark wrongly questions as duplicates
I made the very frustrating experience on Stackoverflow that a question got marked wrongly as duplicate. I spent a day writing the question, he decides in an instant that it's a duplicate, even when it isn't. This usually happens when that guy doesn't truly understand the question and doesn't bother to find the correct answer. He just feels that a similar problem was solved before on SO. But details matter. Yes, there are questions about truncating a file using SetLength(0), but they are different in one crucial point: In those examples, SetLength(0) is not preceded by a Write(). But this is essential, without it there is no problem.
Please, please, be very careful and considerate when blocking others from answering by marking a question as duplicate.
When inspecting FileStream.SetLength() on referencesource.microsoft.com , I noticed this funny looking piece of code:
// Handle buffering updates.
if (_writePos > 0) {
FlushWrite(false);
}
It checks within SetLength() if the internal FileStream buffer has still some write content and writes it first to the file, before executing the rest of SetLength().
A very strange behavior. I could solve this problem by emptying the internal buffer before calling SetLength() using a Flush() first:
var fileName = "test.txt";
using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 8000, FileOptions.None)) {
using (var streamWriter = new StreamWriter(fileStream, Encoding.Default, bufferSize: 8000, leaveOpen: true)) {
streamWriter.WriteLine("123");
streamWriter.Flush();
fileStream.SetLength(0);
streamWriter.WriteLine("abc");
}
}
var fileContent = File.ReadAllText(fileName);
fileContent is now: "abc\\r\\n"
I would be interested to hear if also other feel this is a bug in FileStream ?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.