c# - FileStream:既可以锁定文件,又可以在不截断的情况下读取文件,也可以在不截断的情况下写入文件

本文关键字:文件 情况下 也可以 读取 FileStream 既可以 锁定 | 更新日期: 2023-09-27 18:15:48

我想我的标题不是很清楚。

我会试着解释:

我可以使用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();
}

这样其他程序不能使用该文件,但我也不能删除内容。写入它只会添加字符串,而不会替换内容。

或者我可以不使用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();
}

这样,文件的内容被替换,但它对文件没有锁。

但是我两个都想要。解决方案是什么?

c# - FileStream:既可以锁定文件,又可以在不截断的情况下读取文件,也可以在不截断的情况下写入文件

在您的第一个示例中,您需要在写入流之前重置它,以便替换文件内容,而不是附加到它:

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

如果将流截断为0,它也可以工作,并且不需要以字节为单位计算新文件的大小。

fs.Seek(0,0);
fs.SetLength(0);

如果您想覆盖文件的内容,您需要做两件事:

  1. 设置EndOfFile为0,
  2. 设置文件大小为0。

如果您使用FileStream FileMode。Truncate,它将通过只调用一个系统函数将分配大小和eof设置为0。查看procMon (SysInteranls):operationSeqence_Truncate

如果您使用FileStream FileMode。OpenOrCreate(或Open)并使用fs.Seek(0,0) + fs.SetLength(0)或仅使用fs.SetLength(0),它将通过调用两个系统函数来执行相同的操作。查看procMon (SysInteranls):operationSeqence-SetLengthWithSeekOrOnlySetLength

我倾向于使用第一种方法。代码清晰,没有调用额外的函数。我们只设置模式,不设置其他。

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