C # kullanarak, bir dizindeki tüm dosya ve klasörleri nasıl silebilirim, ancak yine de kök dizini nasıl saklayabilirim?
C # kullanarak, bir dizindeki tüm dosya ve klasörleri nasıl silebilirim, ancak yine de kök dizini nasıl saklayabilirim?
Yanıtlar:
System.IO.DirectoryInfo di = new DirectoryInfo("YourPath");
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
foreach (DirectoryInfo dir in di.GetDirectories())
{
dir.Delete(true);
}
Dizininizde çok sayıda dosya varsa, EnumerateFiles()daha verimlidir GetFiles(), çünkü kullandığınızda EnumerateFiles(), tüm koleksiyonu döndürmeden önce, numaralandırmaya başlamadan önce GetFiles()tüm koleksiyonu belleğe yüklemeniz gereken yerin aksine numaralandırmaya başlayabilirsiniz. Bu alıntıya buradan bakın :
Bu nedenle, birçok dosya ve dizinle çalışırken EnumerateFiles () daha verimli olabilir.
Aynısı EnumerateDirectories()ve için de geçerlidir GetDirectories(). Kod şöyle olur:
foreach (FileInfo file in di.EnumerateFiles())
{
file.Delete();
}
foreach (DirectoryInfo dir in di.EnumerateDirectories())
{
dir.Delete(true);
}
Bu sorunun amacı için, kullanmak için gerçekten bir neden yoktur GetFiles()ve GetDirectories().
Directory.Delete(path, true)
file.Delete().
Evet, bunu yapmanın doğru yolu bu. Kendinize bir "Temizle" (veya "Boş" işlevi olarak adlandırmayı tercih ettiğim gibi) vermek istiyorsanız, bir uzantı yöntemi oluşturabilirsiniz.
public static void Empty(this System.IO.DirectoryInfo directory)
{
foreach(System.IO.FileInfo file in directory.GetFiles()) file.Delete();
foreach(System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true);
}
Bu daha sonra böyle bir şey yapmanıza izin verecektir ..
System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(@"C:\...");
directory.Empty();
EmptyC # 'da zaten var olan bir not string. Adında başka bir şey Emptygörürsem, nesnenin (veya dosya sisteminin) boolboş olup olmadığını söyleyen bir nesne vermek yerine değiştirirse şaşırırdım . Bu nedenle, isimle giderdim Clean.
Is(yani, IsEmptyyerine Empty).
Aşağıdaki kod klasörü özyinelemeli olarak temizler:
private void clearFolder(string FolderName)
{
DirectoryInfo dir = new DirectoryInfo(FolderName);
foreach(FileInfo fi in dir.GetFiles())
{
fi.Delete();
}
foreach (DirectoryInfo di in dir.GetDirectories())
{
clearFolder(di.FullName);
di.Delete();
}
}
new System.IO.DirectoryInfo(@"C:\Temp").Delete(true);
//Or
System.IO.Directory.Delete(@"C:\Temp", true);
Deletedizin yoksa atar, bu yüzden Directory.Existsönce bir kontrol yapmak daha güvenli olur .
Directory.Existsyeterli değil; kontrolden sonra başka bir evre dizini yeniden adlandırmış veya kaldırmış olabilir. Daha güvenlidir try-catch.
Directory.Createçünkü özyinelemenin Directory.Deletene yazık ki eşzamanlı olması garanti edilmez ..
LINQ için sevgiyi de gösterebiliriz :
using System.IO;
using System.Linq;
…
var directory = Directory.GetParent(TestContext.TestDir);
directory.EnumerateFiles()
.ToList().ForEach(f => f.Delete());
directory.EnumerateDirectories()
.ToList().ForEach(d => d.Delete(true));
Buradaki çözümümün performans göstermediğine dikkat edin, çünkü iki kez Get*().ToList().ForEach(...)aynı şeyi kullanıyorum IEnumerable. Bu sorunu önlemek için bir uzantı yöntemi kullanın:
using System.IO;
using System.Linq;
…
var directory = Directory.GetParent(TestContext.TestDir);
directory.EnumerateFiles()
.ForEachInEnumerable(f => f.Delete());
directory.EnumerateDirectories()
.ForEachInEnumerable(d => d.Delete(true));
Bu, uzantı yöntemidir:
/// <summary>
/// Extensions for <see cref="System.Collections.Generic.IEnumerable"/>.
/// </summary>
public static class IEnumerableOfTExtensions
{
/// <summary>
/// Performs the <see cref="System.Action"/>
/// on each item in the enumerable object.
/// </summary>
/// <typeparam name="TEnumerable">The type of the enumerable.</typeparam>
/// <param name="enumerable">The enumerable.</param>
/// <param name="action">The action.</param>
/// <remarks>
/// “I am philosophically opposed to providing such a method, for two reasons.
/// …The first reason is that doing so violates the functional programming principles
/// that all the other sequence operators are based upon. Clearly the sole purpose of a call
/// to this method is to cause side effects.”
/// —Eric Lippert, “foreach” vs “ForEach” [http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx]
/// </remarks>
public static void ForEachInEnumerable<TEnumerable>(this IEnumerable<TEnumerable> enumerable, Action<TEnumerable> action)
{
foreach (var item in enumerable)
{
action(item);
}
}
}
foreach (var dir in info.GetDirectories("*", SearchOption.AllDirectories).OrderByDescending(dir => dir.FullName.Length)) dir.Delete();yararlı olabilir.
directory.EnumerateFiles()ve directory.EnumerateDirectories()kullanmayı düşünün directory.Get*().
IEnumerable<T>.ForEach()uzantımın özet bir XML yorumu var, "İhlal! İhlal! Kirli!".
En basit yol:
Directory.Delete(path,true);
Directory.CreateDirectory(path);
Bunun klasördeki bazı izinleri silebileceğini unutmayın.
private void ClearFolder(string FolderName)
{
DirectoryInfo dir = new DirectoryInfo(FolderName);
foreach(FileInfo fi in dir.GetFiles())
{
try
{
fi.Delete();
}
catch(Exception) { } // Ignore all exceptions
}
foreach(DirectoryInfo di in dir.GetDirectories())
{
ClearFolder(di.FullName);
try
{
di.Delete();
}
catch(Exception) { } // Ignore all exceptions
}
}
Alt klasör olmadığını biliyorsanız, bunun gibi bir şey en kolay olabilir:
Directory.GetFiles(folderName).ForEach(File.Delete)
Denediğim her yöntem, bir noktada System.IO hatalarıyla başarısız oldu. Aşağıdaki yöntem, klasör boş olsa da olmasa da, salt okunur olsa da olmasa da işe yarar.
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C rd /s /q \"C:\\MyFolder"";
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
İşte tüm mesajları okuduktan sonra sona erdiğim araç. Yapar
O ilgilenir
İşlem istisnada durdurulduğundan Directory.Delete kullanmaz.
/// <summary>
/// Attempt to empty the folder. Return false if it fails (locked files...).
/// </summary>
/// <param name="pathName"></param>
/// <returns>true on success</returns>
public static bool EmptyFolder(string pathName)
{
bool errors = false;
DirectoryInfo dir = new DirectoryInfo(pathName);
foreach (FileInfo fi in dir.EnumerateFiles())
{
try
{
fi.IsReadOnly = false;
fi.Delete();
//Wait for the item to disapear (avoid 'dir not empty' error).
while (fi.Exists)
{
System.Threading.Thread.Sleep(10);
fi.Refresh();
}
}
catch (IOException e)
{
Debug.WriteLine(e.Message);
errors = true;
}
}
foreach (DirectoryInfo di in dir.EnumerateDirectories())
{
try
{
EmptyFolder(di.FullName);
di.Delete();
//Wait for the item to disapear (avoid 'dir not empty' error).
while (di.Exists)
{
System.Threading.Thread.Sleep(10);
di.Refresh();
}
}
catch (IOException e)
{
Debug.WriteLine(e.Message);
errors = true;
}
}
return !errors;
}
Aşağıdaki kod dizini temizler, ancak kök dizini orada bırakır (özyinelemeli).
Action<string> DelPath = null;
DelPath = p =>
{
Directory.EnumerateFiles(p).ToList().ForEach(File.Delete);
Directory.EnumerateDirectories(p).ToList().ForEach(DelPath);
Directory.EnumerateDirectories(p).ToList().ForEach(Directory.Delete);
};
DelPath(path);
kullandım
Directory.GetFiles(picturePath).ToList().ForEach(File.Delete);
eski resmi silmek için ve bu klasörde herhangi bir nesneye ihtiyacım yok
FileInfo ve DirectoryInfo yerine File ve Directory ile sadece statik yöntemler kullanmak daha hızlı performans gösterir. ( C # 'da File ve FileInfo arasındaki fark nedir? bölümünde kabul edilen cevaba bakınız ). Yanıt, faydalı yöntem olarak gösterilir.
public static void Empty(string directory)
{
foreach(string fileToDelete in System.IO.Directory.GetFiles(directory))
{
System.IO.File.Delete(fileToDelete);
}
foreach(string subDirectoryToDeleteToDelete in System.IO.Directory.GetDirectories(directory))
{
System.IO.Directory.Delete(subDirectoryToDeleteToDelete, true);
}
}
string directoryPath = "C:\Temp";
Directory.GetFiles(directoryPath).ToList().ForEach(File.Delete);
Directory.GetDirectories(directoryPath).ToList().ForEach(Directory.Delete);
Windows 7'de, Windows Gezgini ile el ile oluşturduysanız, dizin yapısı şuna benzer:
C:
\AAA
\BBB
\CCC
\DDD
Ve C: \ AAA dizinini temizlemek için orijinal soruda önerilen kodu çalıştırdığınızda, çizgi di.Delete(true)her zaman IOException ile başarısız olur. Muhtemelen Windows Gezgini'nde bir tür gecikme / önbellekleme nedeniyle.
Aşağıdaki kod benim için güvenilir bir şekilde çalışıyor:
static void Main(string[] args)
{
DirectoryInfo di = new DirectoryInfo(@"c:\aaa");
CleanDirectory(di);
}
private static void CleanDirectory(DirectoryInfo di)
{
if (di == null)
return;
foreach (FileSystemInfo fsEntry in di.GetFileSystemInfos())
{
CleanDirectory(fsEntry as DirectoryInfo);
fsEntry.Delete();
}
WaitForDirectoryToBecomeEmpty(di);
}
private static void WaitForDirectoryToBecomeEmpty(DirectoryInfo di)
{
for (int i = 0; i < 5; i++)
{
if (di.GetFileSystemInfos().Length == 0)
return;
Console.WriteLine(di.FullName + i);
Thread.Sleep(50 * i);
}
}
Bu sürüm özyinelemeli çağrılar kullanmaz ve salt okunur sorunu çözer.
public static void EmptyDirectory(string directory)
{
// First delete all the files, making sure they are not readonly
var stackA = new Stack<DirectoryInfo>();
stackA.Push(new DirectoryInfo(directory));
var stackB = new Stack<DirectoryInfo>();
while (stackA.Any())
{
var dir = stackA.Pop();
foreach (var file in dir.GetFiles())
{
file.IsReadOnly = false;
file.Delete();
}
foreach (var subDir in dir.GetDirectories())
{
stackA.Push(subDir);
stackB.Push(subDir);
}
}
// Then delete the sub directories depth first
while (stackB.Any())
{
stackB.Pop().Delete();
}
}
Aşağıdaki örnek bunu nasıl yapabileceğinizi göstermektedir. Önce bazı dizinler ve bir dosya oluşturur ve sonra bunları şu yollarla kaldırır Directory.Delete(topPath, true);:
static void Main(string[] args)
{
string topPath = @"C:\NewDirectory";
string subPath = @"C:\NewDirectory\NewSubDirectory";
try
{
Directory.CreateDirectory(subPath);
using (StreamWriter writer = File.CreateText(subPath + @"\example.txt"))
{
writer.WriteLine("content added");
}
Directory.Delete(topPath, true);
bool directoryExists = Directory.Exists(topPath);
Console.WriteLine("top-level directory exists: " + directoryExists);
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.Message);
}
}
Https://msdn.microsoft.com/en-us/library/fxeahc5f(v=vs.110).aspx adresinden alınır .
Yukarıdaki sorunla başa çıkmanın en iyi yolu bu değildir. Ama alternatif bir tane ...
while (Directory.GetDirectories(dirpath).Length > 0)
{
//Delete all files in directory
while (Directory.GetFiles(Directory.GetDirectories(dirpath)[0]).Length > 0)
{
File.Delete(Directory.GetFiles(dirpath)[0]);
}
Directory.Delete(Directory.GetDirectories(dirpath)[0]);
}
DirectoryInfo Folder = new DirectoryInfo(Server.MapPath(path));
if (Folder .Exists)
{
foreach (FileInfo fl in Folder .GetFiles())
{
fl.Delete();
}
Folder .Delete();
}
bu klasörü nasıl sildiğimizi ve Metin kutusunu kullandığımızı kontrol edeceğimizi gösterir
using System.IO;
namespace delete_the_folder
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Deletebt_Click(object sender, EventArgs e)
{
//the first you should write the folder place
if (Pathfolder.Text=="")
{
MessageBox.Show("ples write the path of the folder");
Pathfolder.Select();
//return;
}
FileAttributes attr = File.GetAttributes(@Pathfolder.Text);
if (attr.HasFlag(FileAttributes.Directory))
MessageBox.Show("Its a directory");
else
MessageBox.Show("Its a file");
string path = Pathfolder.Text;
FileInfo myfileinf = new FileInfo(path);
myfileinf.Delete();
}
}
}
using System.IO;
string[] filePaths = Directory.GetFiles(@"c:\MyDir\");
foreach (string filePath in filePaths)
File.Delete(filePath);
Ana telefondan çağrı
static void Main(string[] args)
{
string Filepathe =<Your path>
DeleteDirectory(System.IO.Directory.GetParent(Filepathe).FullName);
}
Bu yöntemi ekle
public static void DeleteDirectory(string path)
{
if (Directory.Exists(path))
{
//Delete all files from the Directory
foreach (string file in Directory.GetFiles(path))
{
File.Delete(file);
}
//Delete all child Directories
foreach (string directory in Directory.GetDirectories(path))
{
DeleteDirectory(directory);
}
//Delete a Directory
Directory.Delete(path);
}
}
Klasörü silmek için bu, Metin kutusunu ve bir düğmeyi kullanan koddur using System.IO;:
private void Deletebt_Click(object sender, EventArgs e)
{
System.IO.DirectoryInfo myDirInfo = new DirectoryInfo(@"" + delete.Text);
foreach (FileInfo file in myDirInfo.GetFiles())
{
file.Delete();
}
foreach (DirectoryInfo dir in myDirInfo.GetDirectories())
{
dir.Delete(true);
}
}
private void ClearDirectory(string path)
{
if (Directory.Exists(path))//if folder exists
{
Directory.Delete(path, true);//recursive delete (all subdirs, files)
}
Directory.CreateDirectory(path);//creates empty directory
}
Directory.CreateDirectory
IO.Directory.Delete(HttpContext.Current.Server.MapPath(path), True)
Bundan daha fazlasına ihtiyacın yok