删除正在使用的文件

Gee*_*der 18 c#

我创建了一个简单的程序来删除C#中的临时文件(为了好玩,而不是一个主要项目),并且遇到锁定文件(使用中)问题.你通常如何排除这些文件?作为参考,我收到错误:

该进程无法访问文件'ExchangePerflog_8484fa31c65c7a31cfcccd43.dat',因为它正由另一个进程使用.

码:

static void Main(string[] args)
    {
        string folderPath = string.Empty;
        folderPath = System.Environment.GetEnvironmentVariable("temp");
        deleteFilesInDirectory(folderPath);
    }

    public static void deleteFilesInDirectory(string folderPath) 
    {

        try
        {
            var dir = new DirectoryInfo(folderPath);
            dir.Attributes = dir.Attributes & ~FileAttributes.ReadOnly;
            dir.Delete(true);
            MessageBox.Show(folderPath + " has been cleaned.");
        }
        catch (System.IO.IOException ex)
        {
            MessageBox.Show(ex.Message); 
            return;

        } 
    }     
Run Code Online (Sandbox Code Playgroud)

dkn*_*ack 16

描述

无法删除当前正由另一个进程使用的文件.但是你可以等到文件没有被锁定.

检查while循环,直到使用此方法解锁文件

protected virtual bool IsFileLocked(FileInfo file)
{
    FileStream stream = null;

    try
    {
        stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    }
    catch (IOException)
    {
        //the file is unavailable because it is:
        //still being written to
        //or being processed by another thread
        //or does not exist (has already been processed)
        return true;
    }
    finally
    {
        if (stream != null)
            stream.Close();
    }

    //file is not locked
    return false;
}
Run Code Online (Sandbox Code Playgroud)

样品

FileInfo file = new FileInfo("PathToTheFile");
while (IsFileLocked(file))
    Thread.Sleep(1000);
file.Delete();
Run Code Online (Sandbox Code Playgroud)

更新

如果要跳过锁定的文件,可以执行此操作.

//
var dir = new DirectoryInfo(folderPath);
foreach(var file in dir.GetFiles()) {
    try
    {
        file.Delete();
    }
    catch (IOException)
    {
        //file is currently locked
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 7

好吧,我遇到了类似的问题。当您在删除文件后不久尝试删除目录时,您必须强制 GC 从当前线程释放文件句柄

public void DisposeAfterTest(string filePath)
    {

        if (File.Exists(filePath))
        {
            File.Delete(filePath);
        }

        GC.Collect();
        GC.WaitForPendingFinalizers();

        if (Directory.Exists(this.TempTestFolderPath))
        {
            Directory.Delete(this.TempTestFolderPath, true);
        }

    }
Run Code Online (Sandbox Code Playgroud)

  • 这是没有将所有文件访问类包装在“using”中的症状。正确处理文件访问句柄,就不会出现此问题。 (2认同)

小智 6

试试下面的代码。只需在文件删除前添加两行:

GC.Collect();
GC.WaitForPendingFinalizers();
Run Code Online (Sandbox Code Playgroud)

  • 实际上,如果您使用 SQLite,这是一个完全有效的注释。见 http://stackoverflow.com/questions/8511901/system-data-sqlite-close-not-releasing-database-file (3认同)
  • 哇,对此有这么多反对票。这确实可能是您无法删除文件的原因。就我而言,我有许多线程处理一个文件(内存映射)。在处理完所有内存映射线程并清理它们自身之后,我试图删除映射文件。它不会让我这样做,因为垃圾收集器没有时间在删除发生之前进行清理。这解决了我的问题,我+1! (2认同)

Rob*_* P. 1

我不相信有任何方法可以提前知道该文件是否正在使用。您可以尝试获取文件的独占锁;但这样你就只是用一种例外来换取另一种例外。

如果您正在打开这些文件,请看看是否可以更好地关闭它们。如果它比这更复杂 - 您可以维护一个“删除列表”并继续重试删除直到成功(可能在具有并发集合的另一个线程上)。

我也不相信有办法强制删除正在使用的文件。