I am trying to filter out the path C:\$Recycle.bin in my file enumeration. How can I do this?
var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories).OrderBy(p => p).ToList();
When I execute the above, I get the error below.
Additional information: Access to the path 'C:\$Recycle.Bin\S-1-5-21-1600837348-2291285090-976156579-500' is denied.
I also want to calc every file's md5. I have:
var mainDirectory = new DirectoryInfo("\\");
var files = GetDirectories(mainDirectory);
List<string> drives = new List<string>();
foreach (var file in files)
{
//Console.WriteLine(file.Name);
drives.Add(mainDirectory + file.Name);
}
MD5 md5 = MD5.Create();
foreach (string file in drives)
{
// hash path
string relativePath = file.Substring("\\".Length + 1);
byte[] pathBytes = Encoding.UTF8.GetBytes(relativePath.ToLower());
md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);
// hash contents
try
{
byte[] contentBytes = File.ReadAllBytes(file);
md5.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0);
md5.TransformFinalBlock(contentBytes, 0, contentBytes.Length);
}
catch(UnauthorizedAccessException)
{
continue;
}
catch
{
continue;
}
Console.WriteLine(BitConverter.ToString(md5.Hash).Replace("-", "").ToLower());
}
Console.ReadKey();
The following could do it for you, but it is a quick and dirty way, because it does not handle any exceptions. I did not regard any readability and it is not fully tested.
static void Main(string[] args)
{
var mainDirectory = new DirectoryInfo("C:\\");
var files = GetFiles(mainDirectory, ".");
foreach (var file in files)
{
Console.WriteLine(file.Name);
}
Console.ReadKey();
}
static IEnumerable<DirectoryInfo> GetDirectories(DirectoryInfo parentDirectory)
{
DirectoryInfo[] childDirectories = null;
try
{
childDirectories = parentDirectory.GetDirectories();
}
catch (Exception)
{
}
yield return parentDirectory;
if (childDirectories != null)
{
foreach (var childDirectory in childDirectories)
{
var childDirectories2 = GetDirectories(childDirectory);
foreach (var childDirectory2 in childDirectories2)
{
yield return childDirectory2;
}
}
}
}
static IEnumerable<FileInfo> GetFiles(DirectoryInfo parentDirectory,
string searchPattern)
{
var directories = GetDirectories(parentDirectory);
foreach (var directory in directories)
{
FileInfo[] files = null;
try
{
files = directory.GetFiles(searchPattern);
}
catch (Exception)
{
}
if (files != null)
{
foreach (var file in files)
{
yield return file;
}
}
}
}
Related
Good afternoon, please tell me how can I add files with the same name to the archive? To be like copying, the file becomes file(1).* and there are two files file and file(1) . I am using Ionic.Zip
string BackupDir = #"C:\Users\Desktop\dir\backup.zip";
string PathToFolder = #"C:\Users\Desktop\dir";
string[] AllFiles = Directory.GetFiles(PathToFolder, "*.*", SearchOption.AllDirectories);
using (ZipFile zip = new ZipFile(BackupDir, Encoding.UTF8))
{
foreach (string file in AllFiles)
{
try
{
DateTime FileCreationTime = File.GetCreationTime(file);
if (FileCreationTime >= DateTime.Now - new TimeSpan(60, 0, 0, 0))
{
Console.WriteLine(file);
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestSpeed;
zip.AddFile(file, "");
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
zip.Save(BackupDir);
}
}
Try this:
//keep track of fileNames
var fileNames = new HashSet<string>(StringCompaer.OridialIgnoreCase);
foreach (string file in AllFiles)
{
try
{
DateTime FileCreationTime = File.GetCreationTime(file);
if (FileCreationTime >= DateTime.Now - new TimeSpan(60, 0, 0, 0))
{
Console.WriteLine(file);
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestSpeed;
var fileName = Path.GetFileName(file);
if (fileNames.Add(fileName))
zip.AddFile(file, ""); //fileName could be added to fileNames = it is unique
else
{
//start with 1
int counter = 1;
//loop till you found a fileName thats not occupied
while (true)
{
//build the new file name
var newFileName = $"{Path.GetFileNameWithoutExtension(fileName)} - {counter}{Path.GetExtension(fileName}";
if (fileNames.Add(newFileName))
{
fileName = newFileName; //use the new fileName
break; //break the loop
}
//increase counter if newFileName is already in the list fileNames
counter++;
}
var zipFileEntry = zip.AddFile(file, "");
zipFileEntry.FileName = fileName;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
zip.Save(BackupDir);
}
Check if file exists and add suffix to it's name.
Something like (Pseudocode):
int nameCount = 1;
fileName = file.Name;
while(fileName exists in archive)
{
nameCount++;
fileName = file.Name + "_" + nameCount;
}
I have the following code:
public static void readtext(string pathtoText)
{
if (File.Exists(pathtoText))
{
string[] lines = System.IO.File.ReadAllLines(pathtoText);
// Display the file contents by using a foreach loop.
foreach (string line in lines)
{
clearPath(line);
}
}
else
{
Console.WriteLine("{0} doesn't exist, or isn't a valid text file", pathtoText);
}
}
public static void clearPath(string path)
{
if(Directory.Exists(path))
{
int directoryCount = Directory.GetDirectories(path).Length;
if(directoryCount > 0)
{
Console.WriteLine("{0} has Subdirectories to Remove", path);
DirectoryInfo di = new DirectoryInfo(path);
foreach (DirectoryInfo dir in di.GetDirectories())
{
dir.Delete(true);
}
}
else
{
Console.WriteLine("{0} has no directories to remove", path);
}
int fileCount = Directory.GetFiles(path).Length;
if (fileCount > 0)
{
Console.WriteLine("{0} has files to Remove", path);
System.IO.DirectoryInfo di = new DirectoryInfo(path);
foreach (FileInfo file in di.GetFiles())
{
try
{
file.Delete();
}
catch(System.IO.IOException)
{
Console.WriteLine("Please Close the following File {0}", file.Name);
}
}
}
}
else
{
Console.WriteLine("Path Doesn't Exist {0}", path);
}
}
My function reads directories from a text file and passes it to clearPath which checks if the directory exists, and if so, cleans it. My problem is that, if a directory doesn't exist, it stops the program(it doesn't move to the next directory to check if it exists and clean, the for each loop just stops) .
How do I get it to the next directory even if specific directory doesn't exist?
it is possible that you have empty lines in your file?
you can try something like that:
foreach (string line in lines)
{
if (!String.IsNullOrWhiteSpace(line))
{
clearPath(line.trim());
}
}
I need to take all file in particular directory and store them in fileinfo array and sort them alphanumerically.
code snippet
string dir = #"C:\tem";
DirectoryInfo directory = new DirectoryInfo(dir);
if (directory != null)
{
FileInfo[] files = directory.GetFiles("*.bmp");
if (files.Length > 0)
{
Console.WriteLine("Files:");
foreach (FileInfo subFile in files)
{
Console.WriteLine(" " + subFile.Name + " (" + subFile.Length + " bytes)");
}
}
}`
currently i am getting output
test_1.bmp test_11.bmp test_2.bmp
but i want the output like
test_1.bmp,test_2.bmp,test_11.bmp
Thanks
You can use LINQ for that:
if (directory != null)
{
FileInfo[] files = directory.GetFiles("*.bmp");
files.Select(f => f.Name).ToList().
OrderBy(x=> Int32.Parse(x.Substring(x.IndexOf('_') + 1, x.IndexOf('.') - x.IndexOf('_') - 1))).
ToList().ForEach(s => Console.WriteLine(s));
}
The output is:
test_1.bmp
test_2.bmp
test_11.bmp
UPDATE:
// Store as FileInfo array
FileInfo[] sortedFiles = files.OrderBy(x => Int32.Parse(x.Name.Substring(x.Name.IndexOf('_') + 1, x.Name.IndexOf('.') - x.Name.IndexOf('_') - 1))).
ToArray();
// Do whatever you want
foreach (FileInfo item in sortedFiles)
{
Console.WriteLine(string.Format("FullPath -> {0}", item.FullName));
}
public static void Main()
{
string dir = #"C:\tem";
var directory = new DirectoryInfo(dir);
FileInfo[] files = directory.GetFiles("*.bmp");
var sortedFiles=files.ToDictionary(k=>GetIntValueFromString(k.Name),v=>v).OrderBy(entry=>entry.Key);
foreach (var file in sortedFiles)
{
Console.WriteLine(file.Value.Name);
}
Console.Read();
}
static int GetIntValueFromString(string input)
{
var result = 0;
var intString = Regex.Replace(input, "[^0-9]+", string.Empty);
Int32.TryParse(intString, out result);
return result;
}
I'm constructing a program to search all .xml inside a folder setted by user (Source folder) and copy all these files to another folder (Destination folder).
My program is able to search all XML within all sub folders from (Source folder), the result returns around 5000 files that are placed on a list, this list is worked later by a function, but he can only work with 31 files, then appears "not responding "and the debugger shows that the program is staying a long time in the execution.
Here is my code:
Button action:
private void btnCopiarSalvar_Click(object sender, EventArgs e)
{
foreach (string name in listFileNames)
{
if (readXML(name ))
{
tbArquivo.Text = name ; //Feedback textbox, tell the current filename
}
}
pbStatus.Increment(50);
cbFinal.Checked = true; //Feedback checkBox, to tell user that the task is over.
}
Function ReadXML
public bool readXML(string name)
{
//foreach (string nome in listaArquivos)
//{ //I tried to the foreach inside, but nothing Works.
try
{
string text = null;
string readBuffer = File.ReadAllText(name);
text = readBuffer.Aggregate(text, (current, b) => current + b);
var encoding = new ASCIIEncoding();
Byte[] textobytes = encoding.GetBytes(text);
if (!File.Exists(destino))
{
string destinoComNomeArquivo = destino + "\\" + Path.GetFileName(nome);
using (FileStream fs = File.Create(destinoComNomeArquivo))
{
foreach (byte textobyte in textobytes)
{
fs.WriteByte(textobyte);
pbProcess.PerformStep();
}
Console.WriteLine("Arquivo gravado " + Path.GetFileName(nome));
}
}
pbProcess.PerformStep();
}
catch (Exception e)
{
Console.WriteLine(e);
}
//}
return true;
}
Error: ContextSwitchDeadlock was detected.
Tried Solution: Disable Managed Debug Assistants.
After disabling the MDA, the programs still only read-copy 31 files (of 5k).
The first thing i recommand is ... don't do that kind of file copy! use the File.Copy function instead.
Try to use this code snipping from MSDN:
void DoCopy(string path)
{
var copytask = new Task(() =>
{
string destinoComNomeArquivo = #"C:\" + Path.GetFileName(path);
DirectoryCopy(path, destinoComNomeArquivo, false);
});
copytask.Start();
}
private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
{
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
DirectoryInfo[] dirs = dir.GetDirectories();
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: "
+ sourceDirName);
}
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(destDirName, file.Name);
file.CopyTo(temppath, false);
}
var counter = 0;
var maxcounter = files.Count();
while (maxcounter < counter)
{
var item = files.ElementAt(counter).Name;
WriteAsnc(item);
counter++;
}
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(destDirName, subdir.Name);
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
}
}
}
const int _maxwritingprocess = Environment.ProcessorCount;
int _currentwritingtasks;
void WriteAsnc(string filepath)
{
_currentwritingtasks++;
var task = Task.Factory.StartNew(() =>
{
XDocument doc = XDocument.Load(filepath);
doc.Elements().First().Add(new XAttribute("Attribute Name","Attribute Value"));
doc.Save(filepath);
_currentwritingtasks--;
});
if(_currentwritingtasks == _maxwritingprocess)
task.Wait();
_currentwritingtasks--;
}
The next point the ContextSwitchDeadlock is a Threading problem and i thing your pbProcess is the source. What does that Process do i don't see anything of that process and i don't thing it is Impotent for your copy
How do I copy a directory to a different drive in C#?
You can use this code to perform your operation:
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
// Check if the target directory exists, if not, create it.
if (Directory.Exists(target.FullName) == false)
{
Directory.CreateDirectory(target.FullName);
}
// Copy each file into it’s new directory.
foreach (FileInfo fi in source.GetFiles())
{
Console.WriteLine(#”Copying {0}\{1}”, target.FullName, fi.Name);
fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir =
target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
below one is also good:
static public void CopyFolder( string sourceFolder, string destFolder )
{
if (!Directory.Exists( destFolder ))
Directory.CreateDirectory( destFolder );
string[] files = Directory.GetFiles( sourceFolder );
foreach (string file in files)
{
string name = Path.GetFileName( file );
string dest = Path.Combine( destFolder, name );
File.Copy( file, dest );
}
string[] folders = Directory.GetDirectories( sourceFolder );
foreach (string folder in folders)
{
string name = Path.GetFileName( folder );
string dest = Path.Combine( destFolder, name );
CopyFolder( folder, dest );
}
}
you can use this function also:
FileSystem.CopyDirectory(sourceDir, destDir);
FileSystem.CopyDirectory(sourceDir, destDir);
FileSystem.CopyDirectory is in a VB namespace and assembly, but that probably doesn't matter.
How to: Copy, Delete, and Move Files and Folders (C# Programming Guide)
http://msdn.microsoft.com/en-us/library/cc148994.aspx
C# Copy Folder Recursively
http://www.csharp411.com/c-copy-folder-recursively/
Here's an extension that will work in .NET 4.0+
var source = new DirectoryInfo(#"C:\Test");
var destination = new DirectoryInfo(#"E:\Test");
source.CopyTo(destination);
Include this file in your project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace System.IO
{
public static class DirectoryInfoExtensions
{
public static void CopyTo(this DirectoryInfo source, DirectoryInfo target)
{
if (!target.Exists)
target.Create();
foreach (var file in source.GetFiles())
file.CopyTo(Path.Combine(target.FullName, file.Name), true);
foreach (var subdir in source.GetDirectories())
subdir.CopyTo(target.CreateSubdirectory(subdir.Name));
}
}
}
private String path;
public int copyAllContents(String destinationFolder, ProgressBar progressBar)
{
int countCopyFiles = 0;
if (!Directory.Exists(destinationFolder))
{ Directory.CreateDirectory(destinationFolder); }
String[] allFilesForCurrentFolder = Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly);
String[] subFoldersAllpath = Directory.GetDirectories(path);
for (int i = 0; i < allFilesForCurrentFolder.Length; i++)
{
try { File.Copy(allFilesForCurrentFolder[i], destinationFolder + "\\" + Path.GetFileName(allFilesForCurrentFolder[i])); countCopyFiles++; progressBar.Value++; }
catch (Exception ex) { Console.WriteLine(ex.Message.ToString()); }
}
if (subFoldersAllpath.Length == 0)
{ return allFilesForCurrentFolder.Length; };
for (int i = 0; i < subFoldersAllpath.Length; i++)
{
this.path = subFoldersAllpath[i];
String[] subFoldersAllpathLastFolder = subFoldersAllpath[i].Split('\\');
countCopyFiles += this.copyAllContents(destinationFolder + "\\" + subFoldersAllpathLastFolder[subFoldersAllpathLastFolder.Length - 1], progressBar);
}
return countCopyFiles;
}
Here's an approach that copies a directory recursively as an async function:
public static async Task CopyDirectoryAsync(string sourceDirectory, string destinationDirectory)
{
if (!Directory.Exists(destinationDirectory))
Directory.CreateDirectory(destinationDirectory);
foreach (var file in Directory.GetFiles(sourceDirectory))
{
var name = Path.GetFileName(file);
var dest = Path.Combine(destinationDirectory, name);
await CopyFileAsync(file, dest);
}
foreach (var subdir in Directory.GetDirectories(sourceDirectory))
{
var name = Path.GetFileName(subdir);
var dest = Path.Combine(destinationDirectory, name);
await CopyDirectoryAsync(subdir, dest);
}
}
public static async Task CopyFileAsync(string sourceFile, string destinationFile)
{
using (var sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
using (var destinationStream = new FileStream(destinationFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
await sourceStream.CopyToAsync(destinationStream);
}