【问题标题】:Having some trouble to delete a file using FileStreams in C#在 C# 中使用 FileStreams 删除文件时遇到一些麻烦
【发布时间】:2023-03-31 22:44:02
【问题描述】:

我正在编写一个使用 C# 文本文件的程序。 我使用解析器类作为文件结构和程序之间的接口。 这个类包含一个StreamReader、一个StreamWriter和一个FileStream。我使用FileStream作为读写器的公共流,否则当它们都打开文件时这两者会发生冲突。

解析器类有一个名为m_path的类变量,这是文件的路径。我已经仔细检查过,路径是正确的。 OpenStreams()ResetStreams() 完美运行,但是在 delete() 函数中调用 CloseStreams() 后,程序转到 catch 子句,因此 File.Delete(m_path) 不会被执行。在其他情况下,CloseStreams() 函数可以完美运行。当我试图关闭StreamReader (m_writer) 时出错,但它确实给出了异常(文件已关闭)。

   /**
     * Function to close the streams.
     */
    private void closeStreams() {
        if (m_streamOpen) {
            m_fs.Close();
            m_reader.Close();
            m_writer.Close(); // Goes wrong

            m_streamOpen = false;
        }
    }

   /**
     * Deletes the file.
     */
    public int delete() {
        try {
            closeStreams(); // Catch after this
            File.Delete(m_path);

            return 0;
        }
        catch { return -1; }
    }

我这样调用函数:

parser.delete();

谁能给我一些建议?

【问题讨论】:

  • doesn't work 是什么意思?
  • MCVE?
  • 你有什么异常吗?
  • 您好,对不起。第一次在 StackOverflow 上提问!我已经编辑了我的问题,所以希望现在更清楚了。
  • 它确实会抛出异常,否则它不会进入 catch 子句。尝试catch (Exception ex){Console.WriteLine(Ex.Message);} 调试您的代码

标签: c# file filestream


【解决方案1】:

您的File.Delete(m_path); 永远不会被调用,因为您在此处遇到异常:

private void closeStreams() {
    if (m_streamOpen) {
        m_fs.Close();
        m_reader.Close();
        m_writer.Close(); // throws an exception here

        m_streamOpen = false;
    }
}

例外是“无法访问已关闭的文件”

原因在Close()StreamReader的文档中有说明:

关闭 System.IO.StreamReader 对象和底层流,并释放与阅读器关联的所有系统资源。

还有一些关于这种行为的文章:

Does disposing streamreader close the stream?

Is there any way to close a StreamWriter without closing its BaseStream?

Can you keep a StreamReader from disposing the underlying stream?

Avoiding dispose of underlying stream

您应该考虑重新编写代码并使用using() 语句。

但是,我对您的代码进行了一些实验,它可以以其他顺序调用 Close()

m_writer.Close();
m_reader.Close();
m_fs.Close();

但是,我认为这只是巧合(我使用了 .NET 4.0,可能这在另一个 .NET 版本中不起作用)。我强烈建议不要这样做。

我对此进行了测试:

using (FileStream fs = new FileStream(m_path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
using (StreamReader reader = new StreamReader(fs))
using (StreamWriter writer = new StreamWriter(fs))
{
  // so some work here

}

File.Delete(m_path);

但是,我知道这可能不适合您,因为您可能希望在您的类中将读写流用作字段。

至少,你有一些样本可以开始......

【讨论】:

  • 感谢您的回答!我确实想保持我的流打开,因为它被使用了很多。如果我理解正确,通过关闭 FileStream (m_fs) 我会自动关闭 m_reader 和 m_writer 的流,所以这就是它给出异常的原因?
  • 反过来:m_reader.Close();关闭 m_fs。我做了一些进一步的检查:如果我交换(在我的示例代码中使用(...第 2 和第 3 行,我在这里也遇到异常。所以可能会更改顺序(首先关闭写入器,然后读取器,文件流)可能真的是一个可行的解决方案。只需进行一些测试和试验......正如 Nils 建议的那样:添加一些 catch() 代码(或对于第一次测试,完全删除所有异常处理,恕我直言,这比全部捕获并忽略更适合试验任何错误(例如在您的代码中)
  • 好吧,我想我明白了。谢谢您的帮助!顺便说一句,在第一次测试时忽略 try-catch 子句的好建议,将来应该会派上用场。
  • 当你 Close() 或 Dispose() 编写器时,它可能会执行 Flush()。当阅读器关闭/处置时,它也会关闭/处置流,因此如果在关闭/处置编写器之前完成此操作,则暗示 Flush() 可能会让您大吃一惊。这可以解释为什么首先关闭或处置作者(也是最内在的使用)有效。阅读器不需要刷新,因此当流被要求关闭/处置时,它更有可能容忍流已经关闭/处置。
【解决方案2】:

File.Delete 应该可以工作,要么你没有调用你的 delete 方法,要么 m_path 是一个无效的路径

【讨论】:

    猜你喜欢
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多