[C#] 檔案、目錄刪除處理心得筆記

檔案、目錄刪除處理心得筆記

本篇重點在刪除整個目錄,作法如下:

  1. 找到沒其他目錄地最下層目錄
  2. 刪除該目錄下所有檔案
  3. 往上一層,找是否有還有其他目錄,若有就跳1,若沒有就刪除該目錄下所有檔案
  4. 判斷是否到刪除操作的最上層,若不是跳3,若是就停止

以下主要操作用到的命名空間如下

using System.IO;

在開始刪除整個目錄或檔案前,必須先做一些前置處理判斷是否有檔案被占用造成無法刪除的問題並做出適當的處理操作!

判斷是否有檔案被使用中

public static bool IsFileInUse(string FileName)
{
	bool inUse = true;
	FileStream fs = null;
	try
	{
		fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.None);
		inUse = false;
	}
	catch
	{
	}
	finally
	{
		if (fs != null)
		fs.Close();
	}

	// true表示正在使用, false沒有使用
	return inUse;
}

自製一個強力刪除檔案的方法(大部分都可以正常釋放並刪除檔案,但還是有特殊情況下無法釋放占用跟刪除 囧)

public static void WipeFile(string FileName, int TimesToWrite)
{
	try
	{
		if (System.IO.File.Exists(FileName))
		{
			// 設定檔案的屬性為一般,為了防止檔案是唯讀
			System.IO.File.SetAttributes(FileName, System.IO.FileAttributes.Normal);
			// 計算檔案儲存 Sector 數目
			double sectors = Math.Ceiling(new System.IO.FileInfo(FileName).Length / 512.0);
			// 建立一個相同大小的虛擬暫存
			byte[] dummyBuffer = new byte[512];
			// 建立一個加密隨機數目產生器
			System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
			// 打開此檔案的 FileStream
			System.IO.FileStream inputStream = new System.IO.FileStream(FileName, System.IO.FileMode.Open, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
			for (int currentPass = 0; currentPass < TimesToWrite; currentPass++)
			{
				// 檔案流位置
				inputStream.Position = 0;
				// 循歷所有的 Sector
				for (int sectorsWritten = 0; sectorsWritten < sectors; sectorsWritten++)
				{
					// 填充假資料到檔案流中
					rng.GetBytes(dummyBuffer);
					// 寫入檔案流
					inputStream.Write(dummyBuffer, 0, dummyBuffer.Length);
				}
			}
			// 清空檔案
			inputStream.SetLength(0);
			// 關閉檔案流
			inputStream.Close();
			// 清空檔案原始日期
			DateTime dt = new DateTime(2037, 1, 1, 0, 0, 0);
			System.IO.File.SetCreationTime(FileName, dt);
			System.IO.File.SetLastAccessTime(FileName, dt);
			System.IO.File.SetLastWriteTime(FileName, dt);
			// 删除檔案
			System.IO.File.Delete(FileName);
		}
	}
	catch (Exception)
	{
	}
}

刪除目錄時,還有一種特殊情況要注意,就是刪除目錄時有時候會出上個刪除操作尚未結束,下一個刪除操作就出錯的問題

我是用 try…catch… 去處理這種情況

最終本篇主要處理方法如下

public static void DeleteFolder(string DirName)
{
	foreach (string d in Directory.GetFileSystemEntries(DirName))
	{
		if (System.IO.File.Exists(d))
		{
			FileInfo fi = new FileInfo(d);
			if (fi.Attributes.ToString().IndexOf("ReadOnly") != -1)
			{
				fi.Attributes = FileAttributes.Normal;
			}
			// 直接刪除資料夾下檔案
			if (IsFileInUse(d))
				WipeFile(d, 20);
			else
				System.IO.File.Delete(d);
		}
		else
		// 遞迴刪除子資料夾
		{
			DeleteFolder(d);
		}
	}

	// 刪除已清空資料夾
	// 避免刪除時序問題,從 .NET4.0 VS2010時就有的問題
	if (Directory.Exists(DirName))
	{
		try
		{
			Directory.Delete(DirName, true);
		}
		catch (IOException)
		{
			System.Threading.Thread.Sleep(100);
			//Directory.Delete(DirName, true);
			DeleteFolder(DirName);
		}
		catch (UnauthorizedAccessException)
		{
			//Directory.Delete(DirName, true);
			DeleteFolder(DirName);
		}
	}
	while (Directory.Exists(DirName))
	{
		System.Threading.Thread.Sleep(10);
	}
}

如上大功告成,收工灑花~ XD