C# - FileStream: both lock a file and at the same time be able to read it without truncating it and write it with truncating it
Asked Answered
D

3

7

I suppose my title isn't that clear.

I'll try to explain:

I can write and read a file using a FileStream

FileStream fs = new FileStream("C:\\Users\\Public\\text.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);

private void button1_Click(object sender, EventArgs e)
{
    fs.Seek(0,0);
    StreamReader sr = new StreamReader(fs);
    textbox.Text = sr.ReadToEnd();
}

private void button2_Click(object sender, EventArgs e)
{
    StreamWriter sw = new StreamWriter(fs);
    sw.Write(textbox.Text);
    sw.Flush();
}

This way other programs can't use the file, but I also can't delete content. Writing to it only adds the string, it doesn't replace the content.

Or I can do it without a FileStream:

private void button1_Click(object sender, EventArgs e)
{
    StreamReader sr = new StreamReader("C:\\Users\\Public\\text.txt");
    textBox1.Text = sr.ReadToEnd();
    sr.Close();
}

private void button2_Click(object sender, EventArgs e)
{
    StreamWriter sw = new StreamWriter("C:\\Users\\Public\\text.txt", false);
    sw.Write(textBox1.Text);
    sw.Close();
}

This way, the content of the file is replaced, but it has no lock on the files.

But I want both. What is the solution?

Dc answered 27/11, 2011 at 19:35 Comment(1)
Truncate with FileStream.SetLength()Iqbal
R
15

In your first example, you need to reset the stream before you write to it in order to replace the file contents, instead of appending to it:

private void button2_Click(object sender, EventArgs e)
{
    fs.Seek(0,0);
    fs.SetLength(Encoding.UTF8.GetBytes(textbox.Text).Length));
    StreamWriter sw = new StreamWriter(fs);
    sw.Write(textbox.Text);
    sw.Flush();
}
Rex answered 27/11, 2011 at 19:37 Comment(2)
No, I don't think this is a good way to do it. What you suggest, for as far as I tested worked like the "insert" mode in texteditors. If my previous text was much longer, only the first characters will be overwritten. For example the file contains "OOOOOOOOOO" and I write "IIIII" to the file in my program, the file will contain "IIIIOOOOO".Dc
@Dc - You need to use SetLength on the FileStream in order to truncate it. Answer updated, assuming UTF8.Rex
C
1

If you truncate the stream down to 0, it will also work and no need to calculate the new file size in bytes.

fs.Seek(0,0);
fs.SetLength(0);
Chilli answered 23/10, 2017 at 19:18 Comment(0)
A
0

If you want overwrite content of file, you need to do two things:

  1. set EndOfFile to 0,
  2. set Size of file to 0.

If you use FileStream FileMode.Truncate, it will set allocation size and eof to 0 by call only one system function. See from procMon (SysInteranls): operationSeqence_Truncate

If you use FileStream FileMode.OpenOrCreate (or Open) and using fs.Seek(0,0) + fs.SetLength(0) or only fs.SetLength(0), it will do the same by calling now two system functions. See from procMon (SysInteranls): operationSeqence-SetLengthWithSeekOrOnlySetLength

I prefare to use the first way. Code is clear and no additional function is calling. We set mode and nothing else.

using (var fileStream = new FileStream(path, FileMode.Truncate, FileAccess.Write, FileShare.Read))
using (var binaryWriter = new BinaryWriter(fileStream, Encoding.Unicode))
{
  binaryWriter.Write(bytes, 0, bytes.Length);
}
Allodial answered 17/3, 2022 at 7:56 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.