我创建了一个简单的程序来删除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;
}
}
答案 0 :(得分:15)
无法删除其他进程当前正在使用的文件。但是你可以等到文件没有被锁定。
检查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;
}
FileInfo file = new FileInfo("PathToTheFile");
while (IsFileLocked(file))
Thread.Sleep(1000);
file.Delete();
如果您想跳过锁定的文件,可以执行此操作。
//
var dir = new DirectoryInfo(folderPath);
foreach(var file in dir.GetFiles()) {
try
{
file.Delete();
}
catch (IOException)
{
//file is currently locked
}
}
答案 1 :(得分:4)
我遇到了类似的问题。当您在删除文件后立即尝试删除目录时,必须强制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);
}
}
答案 2 :(得分:1)
使用dknaack的代码。就我而言,这行得通。
FileInfo file = new FileInfo("xyz.txt");
try
{
for (int tries = 0; IsFileLocked(file) && tries < 5; tries++)
Thread.Sleep(1000);
file.Delete();
}
catch (IOException exception)
{
Console.WriteLine(string.Format("File locked: {0}", exception);
}
答案 3 :(得分:0)
我不相信如果文件正在使用中,您可以提前知道。您可以尝试获取文件的独占锁定;但那时你只是为另一个交易一个例外。
如果这些是您正在打开的文件,请查看您是否无法更好地关闭它们。如果它比那更复杂 - 你可以维护一个'删除列表'并继续重试删除直到它成功(在另一个并发收集的线程上)。
我也不相信强行删除正在使用的文件。
答案 4 :(得分:0)
以下代码将删除目录及其所有子目录(不包括锁定文件)中的文件,并获取未删除文件的列表。如果只考虑当前目录,可以将SearchOption更改为TopDirectoryOnly。
string []files = Directory.GetFiles(dirPath,"*.*", SearchOption.AllDirectories); //this gets the files in all subdirectories as well
List<string> lockedFiles = new List<string>();
foreach(string file in files)
{
try
{
file.Delete();
}
catch (IOException)
{
lockedFiles.Add(file);
}
}
答案 5 :(得分:0)
您只需要调用一种方法,即WipeFile,代码如下所示。因此,您真正需要做的就是调用WipeFile并提供要删除的文件的完整路径,以及您想要覆盖它的次数。
public void WipeFile(string filename, int timesToWrite)
{
try
{
if (File.Exists(filename))
{
// Set the files attributes to normal in case it's read-only.
File.SetAttributes(filename, FileAttributes.Normal);
// Calculate the total number of sectors in the file.
double sectors = Math.Ceiling(new FileInfo(filename).Length/512.0);
// Create a dummy-buffer the size of a sector.
byte[] dummyBuffer = new byte[512];
// Create a cryptographic Random Number Generator.
// This is what I use to create the garbage data.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
// Open a FileStream to the file.
FileStream inputStream = new FileStream(filename, FileMode.Open);
for (int currentPass = 0; currentPass < timesToWrite; currentPass++)
{
UpdatePassInfo(currentPass + 1, timesToWrite);
// Go to the beginning of the stream
inputStream.Position = 0;
// Loop all sectors
for (int sectorsWritten = 0; sectorsWritten < sectors; sectorsWritten++)
{
UpdateSectorInfo(sectorsWritten + 1, (int) sectors);
// Fill the dummy-buffer with random data
rng.GetBytes(dummyBuffer);
// Write it to the stream
inputStream.Write(dummyBuffer, 0, dummyBuffer.Length);
}
}
// Truncate the file to 0 bytes.
// This will hide the original file-length if you try to recover the file.
inputStream.SetLength(0);
// Close the stream.
inputStream.Close();
// As an extra precaution I change the dates of the file so the
// original dates are hidden if you try to recover the file.
DateTime dt = new DateTime(2037, 1, 1, 0, 0, 0);
File.SetCreationTime(filename, dt);
File.SetLastAccessTime(filename, dt);
File.SetLastWriteTime(filename, dt);
// Finally, delete the file
File.Delete(filename);
WipeDone();
}
}
catch(Exception e)
{
WipeError(e);
}
}
我添加了一些事件只是为了能够跟踪过程中发生的事情。
答案 6 :(得分:-1)
尝试以下代码。 只需在删除文件前添加两行:
GC.Collect();
GC.WaitForPendingFinalizers();