使用C#检查文件是否正在使用

3
我看到了以下两个问题: 如何检查文件是否正在使用中 有没有方法可以检查文件是否正在使用中 但是它们都没有提供我所需要的所有信息,我需要更多关于一些答案的澄清,但这些问题已经几年了,所以我不确定此时是否应该从那里获取答案。因此,我发布了一个新问题,类似于:
public string myFile;
myFile = @"C:\somepath\somefile.pdf";

if (myFile isinuseorwhatever)
{
     MessageBox.Show("File is in use!! Close it and try again");
     return;
}
else
{
     MessageBox.Show("That worked. Good job!")
     //Do Stuff and lots of lines of stuff.
}

我可以使用异常处理来解决这个问题,但问题在于我需要在运行许多代码之前进行检查。

我感觉我需要创建一个类来进行检查,然后运行该类。老实说,我对编程还比较新,所以我不太清楚类是如何工作的。

我知道可以使用 trycatch,但这里无法使用它们,因为异常发生在 try 块的最后几行代码中,所以所有的操作都会在遇到异常之前完成。例如,这个程序会复制一个文件,重命名它,将它移动到另一个目录,然后删除原始文件,这是它做的最后一件事情。如果用户正在使用该文件,程序将执行所有操作,但当尝试删除该文件时,会抛出一个异常。我需要在复制、重命名、移动等操作之前抛出异常。


2
你正在过度努力。你应该尝试重命名文件。捕获任何异常,这意味着文件很可能正在使用中。如果没有异常,移动文件(移动意味着没有原始文件需要删除,因为它已经被移动了 - 只有在复制时才需要删除)。按照这个顺序进行操作,这意味着你所链接的帖子中的任何解决方案都将适用于你。 - Ken White
3个回答

5
您可以使用 FileStreamFileShare.None 来独占地访问锁定文件。因此,如果我们想要实现上述第一种请求:

  1. 检查文件是否正在使用,如果是,则通知用户
  2. 如果没有被锁定,则锁定它,这样就不会有人打开它
  3. 复制文件
  4. 重命名文件

您可以实现以下代码:

try
{

    using (Stream stream = new FileStream("1.docx", FileMode.Open, FileAccess.ReadWrite, FileShare.None))
    {
        // Here you can copy your file
        // then rename the copied file
    }
}
catch (Exception ex)
{
    MessageBox.Show("File is in use!! Close it and try again");
    return;
}

我想你知道如何复制和重命名文件(如果不知道,请在评论中提问,我会在这里添加代码)。 你的问题的第二部分有点棘手。因为你不能使用Filestream来删除文件。一旦你释放了filestream并调用File.Delete("YourFile.doc"),就有可能在那个时刻正好有一些访问它。 我建议你在文件被锁定时截断它,这样其他用户就不能使用它。你也可以在循环中保持进程,直到文件被释放。代码看起来像这样:

try
{
    using (Stream stream = new FileStream("1.docx", FileMode.Open, FileAccess.ReadWrite, FileShare.None))
    {
        // Here you can copy your file
        // then rename the copied file
        using (StreamWriter writer = new StreamWriter(stream, Encoding.Unicode))
        {
            writer.Write(""); // truncate the file, making it unusable to others
        }
    }
    while (true)
    {
        try
        {
            File.Delete("1.docx");
        }
        catch 
        {
        }
    }
}
catch (Exception ex)
{
    MessageBox.Show("File is in use!! Close it and try again");
    return;
}

2

当前@code-pope接受的答案在try-catch中包含了太多的代码,它将每个异常都视为“文件正在使用”,而实际上异常也可能是由其他原因引起的。

我会这样做:

string path = "some path";
FileStream fs = null; 
try
{
    fs = new FileStream("1.docx", FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch(Exception ex)
{
    //ops, cannot open file, better not keep on
    MessageBox.Show("File is in use!! Close it and try again");
    return;
}

// lets go on now...
using (fs)
{
    // do your work
}

在你的代码中,删除操作没有被实现。他还要求删除文件。如果你想要删除文件,你需要另一个try,catch。 - Code Pope

1

使用布尔值,如果尝试打开文件时抛出异常,则将其设置为false。

示例:

    string path = "Your Path";
    bool available = true;
    try
    {
        using (FileStream fs = File.Open(path, FileMode.Open))
        {

        }
    }
    catch(Exception ex)
    {
        available = false;
    }

1
这样做不行。一旦你关闭文件,其他进程可能会锁定、删除、重命名或以其他方式使文件不可用。当你通过catch块时,不能保证available的值告诉你文件的真实状态。 - Jim Mischel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接