uso - eliminar un fichero en c#
¿Cómo borrar todos los archivos y carpetas de un directorio? (29)
Utilizando C #, ¿cómo puedo eliminar todos los archivos y carpetas de un directorio, pero mantener el directorio raíz?
Aquí está la herramienta con la que terminé después de leer todas las publicaciones. Lo hace
- Borra todo lo que se puede borrar
- Devuelve falso si algunos archivos permanecen en la carpeta.
Se trata de
- Archivos de solo lectura
- Retraso de eliminación
- Archivos bloqueados
No utiliza Directory.Delete porque el proceso se cancela con excepción.
/// <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;
}
Basado en el blog hiteshbi, probablemente debería asegurarse de que el archivo sea de lectura y escritura.
private void ClearFolder(string FolderName)
{
DirectoryInfo dir = new DirectoryInfo(FolderName);
foreach (FileInfo fi in dir.GetFiles())
{
fi.IsReadOnly = false;
fi.Delete();
}
foreach (DirectoryInfo di in dir.GetDirectories())
{
ClearFolder(di.FullName);
di.Delete();
}
}
Si sabe que no hay subcarpetas, algo como esto puede ser lo más fácil:
Directory.GetFiles(folderName).ForEach(File.Delete)
El siguiente código borrará la carpeta de forma recursiva:
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();
}
}
El siguiente código limpiará el directorio, pero dejará el directorio raíz allí (recursivo).
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);
El siguiente ejemplo muestra cómo puedes hacer eso. Primero crea algunos directorios y un archivo y luego los elimina a través de 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);
}
}
Se toma de https://msdn.microsoft.com/en-us/library/fxeahc5f(v=vs.110).aspx .
El uso de métodos solo estáticos con Archivo y Directorio en lugar de FileInfo y DirectoryInfo funcionará más rápido. (vea la respuesta aceptada en ¿Cuál es la diferencia entre File y FileInfo en C #? ). La respuesta se muestra como método de utilidad.
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);
}
}
En Windows 7, si lo acaba de crear manualmente con el Explorador de Windows, la estructura de directorios es similar a esta:
C:
/AAA
/BBB
/CCC
/DDD
Y ejecutando el código sugerido en la pregunta original para limpiar el directorio C: / AAA, la línea di.Delete(true)
siempre falla con la excepción IOException "El directorio no está vacío" cuando se intenta eliminar BBB. Probablemente se deba a algún tipo de retraso / almacenamiento en caché en el Explorador de Windows.
El siguiente código funciona de manera confiable para mí:
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);
}
}
Esta versión no utiliza llamadas recursivas y resuelve el problema de solo lectura.
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();
}
}
Esto mostrará cómo eliminamos la carpeta y verificamos si usamos el cuadro de texto.
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();
}
}
}
La forma más sencilla:
Directory.Delete(path,true);
Directory.CreateDirectory(path);
Tenga en cuenta que esto puede eliminar algunos permisos en la carpeta.
Llamar desde principal
static void Main(string[] args)
{
string Filepathe =<Your path>
DeleteDirectory(System.IO.Directory.GetParent(Filepathe).FullName);
}
Añade este método
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);
}
}
Lo único que debe hacer es establecer el optional recursive parameter
en True
.
Directory.Delete("C:/MyDummyDirectory", True)
Gracias a .NET. :)
No es la mejor manera de lidiar con el problema anterior. Pero es una alternativa ...
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]);
}
Para eliminar la carpeta, este es un código que usa el cuadro de texto y un botón que 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);
}
}
Sí, esa es la forma correcta de hacerlo. Si desea darse una función "Limpiar" (o, como prefiero llamarlo, función "Vaciar"), puede crear un método de extensión.
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);
}
Esto te permitirá hacer algo como ...
System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(@"C:/...");
directory.Empty();
También podemos mostrar amor por LINQ :
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));
Tenga en cuenta que mi solución aquí no es Get*().ToList().ForEach(...)
, porque estoy usando Get*().ToList().ForEach(...)
que genera el mismo IEnumerable
dos veces. Utilizo un método de extensión para evitar este problema:
/// <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);
}
}
}
Este es el método de extensión:
new System.IO.DirectoryInfo(@"C:/Temp").Delete(true);
//Or
System.IO.Directory.Delete(@"C:/Temp", true);
Todos los métodos que probé, han fallado en algún momento con los errores de System.IO. El siguiente método es seguro, incluso si la carpeta está vacía o no, es de solo lectura o no, etc.
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);
Utilice el método GetDirectories de DirectoryInfo.
foreach (DirectoryInfo subDir in new DirectoryInfo(targetDir).GetDirectories())
subDir.Delete(true);
foreach (string file in System.IO.Directory.GetFiles(path))
{
System.IO.File.Delete(file);
}
foreach (string subDirectory in System.IO.Directory.GetDirectories(path))
{
System.IO.Directory.Delete(subDirectory,true);
}
DirectoryInfo Folder = new DirectoryInfo(Server.MapPath(path));
if (Folder .Exists)
{
foreach (FileInfo fl in Folder .GetFiles())
{
fl.Delete();
}
Folder .Delete();
}
IO.Directory.Delete(HttpContext.Current.Server.MapPath(path), True)
No necesitas más que eso
System.IO.Directory.Delete(installPath, true);
System.IO.Directory.CreateDirectory(installPath);
System.IO.DirectoryInfo di = new DirectoryInfo("YourPath");
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
foreach (DirectoryInfo dir in di.GetDirectories())
{
dir.Delete(true);
}
Si su directorio puede tener muchos archivos, EnumerateFiles()
es más eficiente que GetFiles()
, porque cuando usa EnumerateFiles()
puede comenzar a enumerarlo antes de que se devuelva toda la colección, en lugar de GetFiles()
donde debe cargar el Toda la colección en memoria antes de comenzar a enumerarla. Vea esta cita here :
Por lo tanto, cuando trabaja con muchos archivos y directorios, EnumerateFiles () puede ser más eficiente.
Lo mismo se aplica a EnumerateDirectories()
y GetDirectories()
. Entonces el código sería:
foreach (FileInfo file in di.EnumerateFiles())
{
file.Delete();
}
foreach (DirectoryInfo dir in di.EnumerateDirectories())
{
dir.Delete(true);
}
Para el propósito de esta pregunta, realmente no hay razón para usar GetFiles()
y GetDirectories()
.
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
}
private void ClearFolder(string FolderName)
{
DirectoryInfo dir = new DirectoryInfo(FolderName);
foreach (FileInfo fi in dir.GetFiles())
{
fi.IsReadOnly = false;
fi.Delete();
}
foreach (DirectoryInfo di in dir.GetDirectories())
{
ClearFolder(di.FullName);
di.Delete();
}
}
string directoryPath = "C:/Temp";
Directory.GetFiles(directoryPath).ToList().ForEach(File.Delete);
Directory.GetDirectories(directoryPath).ToList().ForEach(Directory.Delete);
using System.IO;
string[] filePaths = Directory.GetFiles(@"c:/MyDir/");
foreach (string filePath in filePaths)
File.Delete(filePath);
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));
using System;
using System.IO;
namespace DeleteFoldersAndFilesInDirectory
{
class Program
{
public static void DeleteAll(string path)
{
string[] directories = Directory.GetDirectories(path);
string[] files = Directory.GetFiles(path);
foreach (string x in directories)
Directory.Delete(x, true);
foreach (string x in files)
File.Delete(x);
}
static void Main()
{
Console.WriteLine("Enter The Directory:");
string directory = Console.ReadLine();
Console.WriteLine("Deleting all files and directories ...");
DeleteAll(directory);
Console.WriteLine("Deleted");
}
}
}