为什么在StreamReader.Read周围使用using(){}允许之后删除文件?

问题描述 投票:1回答:2

所以我正在为学校项目尝试Windows表单并继续遇到错误:

System.IO.IOException('进程无法访问文件'C:\ XXXX \ YYYY.txt',因为它正由另一个进程使用。'

当试图通过File.Delete(path);事件删除文件(button_click)时。

事实证明,当我改变以下方法时:

private void updateTxt(){
  String tempStore = "";
  iDLbl1.Text = "ID:" + id;//iDLbl1 is ID Label 1
  try
  {
      StreamReader Reader = new StreamReader(path);
      while (!Reader.EndOfStream)
        { tempStore += Reader.ReadLine() + "\n"; }
  }
  catch { noIDLbl.Visible = true; }
  rTxtBox.Text = tempStore;//rTxtBox is Rich Text Box
} 

private void updateTxt(){
    String tempStore = "";
    iDLbl1.Text = "ID:" + id;//iDLbl1 is ID Label 1
    try
    {
        using(StreamReader Reader = new StreamReader(path))
        {
            while (!Reader.EndOfStream)
            { tempStore += Reader.ReadLine() + "\n"; }
        }

    }
    catch { noIDLbl.Visible = true; }
    rTxtBox.Text = tempStore;//rTxtBox is Rich Text Box
}

异常停止弹出。虽然代码有效,但我根本不知道究竟是什么原因造成的......逻辑似乎没有为我点击,所以任何人都知道为什么会发生这种情况或者有更合理的解决方案?如果需要请求澄清,这是构造函数以防万一:

public FindID(String ID)
{
    id = ID;
    path = @"C:\XXXX\YYYY\"+ID+".txt";
    InitializeComponent();
    updateTxt();
}
c# winforms streamreader using system.io.file
2个回答
6
投票

在你的第一种方法中,由于你不是Close()ing或Dispose()ing你的StreamReader,相关的文件句柄将被保留,直到垃圾收集器收集StreamReader,这可能是几秒钟,甚至几分钟后(请不要尝试控制或影响GC)。

在你的第二种方法中,using范围在范围的末尾处放置(并关闭)StreamReader(与}匹配的结束using),这在使用任何实现IDisposable的类时是正确的做法。然后,它会释放文件的任何句柄,允许删除它。 using块也具有try / finally块的保证,因此即使存在IO异常,也会调用Dispose

using(StreamReader Reader = new StreamReader(path)) // try {StreamReader Reader = ...}
{
     ...
} <- equivalent to finally {Reader.Dispose();}

但是,由于您似乎只想立即实现行分隔文本文件中的所有行,您可以使用File.ReadAllLines一步完成此操作 - 即根本不需要StreamReader

var tempStore = string.Join(Environment.NewLine, File.ReadAllLines(path));

3
投票

在第二个代码中,一旦您的代码块将执行,StreamReader将被处理掉。由于StreamReader将被丢弃,因此当前进程不会锁定该文件。

在您的第一个代码中,您可以通过在代码末尾处理它们来完成相同的操作。

© www.soinside.com 2019 - 2024. All rights reserved.