I am trying to move a file if it contains a certain string, Code below
foreach (FileInfo file in files)
{
//reads the file contents
string MessageContents = File.ReadAllText(file.FullName);
//checks if the textwords are present in the file
foreach (string Keyword in textwords)
{
//if they are file is moved to quarantine messages
if (MessageContents.Contains(Keyword))
{
try
{
File.Move(file.FullName, File_quarantine);
}
catch (IOException cannot_Move_File)
{
MessageBox.Show("The process has failed: {0}", cannot_Move_File.ToString());
}
break;
}
//else it is moved To valid messages
else
{
try
{
File.Move(file.FullName, File_Valid);
}
catch (IOException cannot_Move_File)
{
MessageBox.Show("The process has failed: {0}", cannot_Move_File.ToString());
}
break;
}
}
}
}
However the process always fails with the error A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll
I am unsure as to why this is happening, any help would be greatly appreciated.
You still have a lock on the file, because you opened a stream to it. Move your logic of moving the file out of the reading of the file.
This should produce the desired result;
foreach (FileInfo file in files)
{
String messageContents = File.ReadAllText(file.FullName);
bool toQuarantine = textwords.Any(keyWord => messageContents.Contains(keyWord));
try
{
File.Move(file.FullName, toQuarantine ? File_quarantine : File_Valid);
}
catch (IOException cannot_Move_File)
{
MessageBox.Show("The process has failed: {0}", cannot_Move_File.ToString());
}
}
Basically you have a lock on the file. You can't move it while you're reading it.
If the files are relatively small, you can use a technique like this:
String content = File.ReadAllText( filename );
// at this point, the file is not locked, unlike the
// way it is in your question. you are free to move it
foreach (String keyword in keywords) {
if (content.Contains(keyword)) {
// Move file
break;
}
}
Related
I want to get the full path of the file named wampmanager.conf on disk D. I coded the following for this:
private static string Scan(string path, string file)
{
try
{
foreach (var dir in Directory.EnumerateDirectories(path))
{
foreach (var fl in Directory.EnumerateFiles(dir, file))
{
if (!string.IsNullOrEmpty(fl))
{
return fl;
}
}
}
}
catch (Exception)
{
// ignored
}
return null;
}
var wmc = Scan(#"D:\", "wampmanager.conf");
MessageBox.Show(wmc);
It always returns null even though the wampmanager.conf file exists on the disk D. I guess it goes to a directory like d:\recovery\ that I don't have access to, then it crashes into a catch and returns null. But when I don't use try catch I always get access authorization error. How can I deal with this problem?
For each directory you must use SearchOption.AllDirectories to Includes the current directory and all its subdirectories in a search operation. Try this function:
private static string Scan(string path, string file)
{
foreach (var dir in Directory.EnumerateDirectories(path))
try
{
string[] files = Directory.GetFiles(dir, file, SearchOption.AllDirectories);
if (files.Length > 0)
{
return files[0];
}
}
catch (Exception e)
{
string s = e.Message;
}
return "not found!";
}
I am trying to find out if a text file contains a string. The string could be any of the string's that are contained within the list textwords, if a word is contained within the text file then it will copy the file it to a new location
The issue I am having is that the program does not loop through all the words in textwords it only takes the first value of the list. How do I get it to loop through all the strings within the list and see if they are contained within the text file before copying the file.
Any help would be appreciated.
My code is below,
foreach (FileInfo file in files)
{
//reads the file contents
bool nextouterloop = false;
using (StreamReader ReadMessage = new StreamReader(file.FullName))
{
String MessageContents = ReadMessage.ReadToEnd();
//checks if the textwords are present in the file
foreach ( string Keyword in textwords )
{
//if they are file is moved to quarantine messages
if ( MessageContents.Contains(Keyword) )
{
try
{
File.Copy(file.FullName,
#"F:\UNI\Year 2\Tri 2\Software Engineering Methods\Coursework\Noogle system\Quarantin_Messages\" +
file);
}
catch ( IOException cannot_Move_File )
{
MessageBox.Show(cannot_Move_File.ToString());
}
break;
}
//else it is moved To valid messages
else
{
try
{
File.Copy(file.FullName,
#"F:\UNI\Year 2\Tri 2\Software Engineering Methods\Coursework\Noogle system\Valid_Messages\" +
file);
}
catch ( IOException cannot_Move_File )
{
MessageBox.Show(cannot_Move_File.ToString());
}
break;
}
}
}
}
But you are performing the copy and break in the first pass
No kidding it does not get to the second word
foreach (FileInfo file in files)
{
string path = #"F:\UNI\Year 2\Tri 2\Software Engineering Methods\Coursework\Noogle system\Valid_Messages\";
//reads the file contents
using (StreamReader ReadMessage = new StreamReader(file.FullName))
{
String MessageContents = ReadMessage.ReadToEnd();
//checks if the textwords are present in the file
foreach (string Keyword in textwords)
{
if (MessageContents.Contains(Keyword))
{
path = #"F:\UNI\Year 2\Tri 2\Software Engineering Methods\Coursework\Noogle system\Quarantin_Messages\"
break;
}
}
}
// let the StreamReader close down before the copy
// don't need it anymore
try
{
File.Copy(file.FullName, path + file);
}
catch (IOException cannot_Move_File)
{
MessageBox.Show(cannot_Move_File.ToString());
}
}
You have 'break' statements in both the 'if' and 'else' conditions. Therefore it will never loop beyond the first string.
You are using break at the end of the statements. This will break the loop. You should use continue instead.
But this continue will be useless since you're using just an if-else function to do copy the file and nothing more. You can get rid of the break in this case. The program would execute the if statement and at the end of the block it will ignore the else statement (or vice-versa) and iterate the loop.
You have "break" causing it to stop after first iteration. Also a search like this wouldn't work. A better (yet not perfect) one is:
foreach (FileInfo file in files)
{
//reads the file contents
var content = File.ReadAllText(file.FullName);
if (textwords.Any(tw => Regex.IsMatch(content, #"\b" + tw.Trim() + #"\b", RegexOptions.IgnoreCase))
{
try
{
File.Move(file.FullName, Path.Combine(#"F:\UNI\Year 2\Tri 2\Software Engineering Methods\Coursework\Noogle system\Quarantin_Messages", file.Name));
}
catch (IOException cannot_Move_File)
{
MessageBox.Show(cannot_Move_File.ToString());
}
}
else
{
//else it is moved To valid messages
try
{
File.Copy(file.FullName, #"F:\UNI\Year 2\Tri 2\Software Engineering Methods\Coursework\Noogle system\Valid_Messages\" + file.Name);
}
catch (IOException cannot_Move_File)
{
MessageBox.Show(cannot_Move_File.ToString());
}
}
}
I created folder with no name using (alt + 0160) while I search with c# it stuck in infinite loop and create exception of "Stack Over Flow"
My method is given which i am using for Search.
public void getTotatFoldersAndFilesCount(DirectoryInfo objDirs, System.ComponentModel.BackgroundWorker worker)
{
try{
if (worker.CancellationPending == true)
{ return; }
FileInfo[] objFiles = null;
numFoldersCount++;
if ((objDirs.Attributes & FileAttributes.ReparsePoint) != 0)
{ return;}
try
{
objFiles = objDirs.GetFiles(searchPatteren);
}
catch (UnauthorizedAccessException e)
{ }
catch (System.IO.DirectoryNotFoundException e)
{ }
catch (System.StackOverflowException ex)
{ }
if (objFiles != null)
{
foreach (FileInfo objFile in objFiles)
{
numFilesCount++;
}
foreach (DirectoryInfo objDir in objDirs.GetDirectories())
{
getTotatFoldersAndFilesCount(objDir, worker);
}
}
objFiles = null;
}
catch (Exception ex)
{
ErrorLogger("Error in Total Folder and File Count - Directory Name: " + objDirs.Name);
ErrorLogger(ex.Message);
}
}
This can be avoided by a simple change:
In the directory enumeration code, change the for loop to:
foreach (DirectoryInfo objDir in new DirectoryInfo(objDirs.FullName + Path.DirectorySeparatorChar).GetDirectories(searchPatteren))
{
getTotatFoldersAndFilesCount(objDir, worker);
}
When enumerating blank folder, the directory name is a white space. When initializing the DirectoryInfo object, the whitespace is trimmed causing the function to always loop trough the same directory. Adding the DirectorySeperatorChar ("\") in most of the cases solves the issue.
I google this question and find the solution by given link.
by adding single slash at the end of the directory path it will not go into infinite loop.
first i was doing this.
getTotatFoldersAndFilesCount(objDir, worker);
and now replace it with this. It solved my problem,
DirectoryInfo nDI = new DirectoryInfo(objDir.FullName + #"\");
getTotatFoldersAndFilesCount(nDI, worker);
link is given.
http://tiku.io/questions/4277530/getdirectories-fails-to-enumerate-subfolders-of-a-folder-with-255-name
I am trying to build a program will show all files and directories in a given directory , and the size of each item .
for the folders size I used https://stackoverflow.com/a/2981241/4645644 as it seems nice and understandable for me.
I noticed that when I try to use GetFiles() or GetDirecories() I get exception if there is none exist .
I tried to write to console when this happens but nothing is written to the console yet it doesnt do the try part and I don't understand what is happening or what I missed.
public static void Main(string[] args)
{
Console.WriteLine("write path folder");
string path = Console.ReadLine();
DirectoryInfo di = new DirectoryInfo(#path);
//int check=1;
bool iterating = true;
if (!Directory.Exists(path))
{
Console.WriteLine("{0} not found , path is wrong or there is no such directory", path);
}
else
{
while (iterating)
{
Console.WriteLine("Name,Root,Parent -> {0},{1},{2}", di.Name, di.Root, di.Parent);
Console.WriteLine("{0} full size is : {1}", di.Name, DirSize(di));
try
{
foreach (DirectoryInfo sfolder in di.GetDirectories())
{
Console.WriteLine("Folder Name: {0} , Folder size - {1} KB", sfolder.Name, DirSize(sfolder));
}
}
catch
{
Console.WriteLine("No subfolder in thie folder : {0}", di.FullName);
}
try
{
foreach (FileInfo sfile in di.GetFiles())
{
Console.WriteLine("File name : {0} , File size - {1} KB", sfile.Name, sfile.Length);
}
}
catch
{
Console.WriteLine("No files in thie folder : {0}", di.FullName);
}
iterating = false;
}
}
}
Add Console.ReadKey(); at the end of your Main method. So, application will not close after executing.
String userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
String dr = #"C:\Users\" + userName + #"\AppData\temp";
DirectoryInfo dir = new DirectoryInfo(#dr);
foreach (FileInfo file in dir.GetFiles())
{
file.Delete();
}
foreach (DirectoryInfo dire in dir.GetDirectories())
{
dire.Delete(true);
}
i was using this for deleting contents of a folder and that should be depending upon the username of the computer & i have provided the admin privilege
but when any file doesnt delete it stops working at that file. i want this process to complete
String userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
String dr = #"C:\Users\" + userName + #"\AppData\temp";
DirectoryInfo dir = new DirectoryInfo(#dr);
foreach (FileInfo file in dir.GetFiles())
{
try
{
file.Delete();
}
catch (IOException ex)
{//Log ex.message
continue;
}
}
foreach (DirectoryInfo dire in dir.GetDirectories())
{
try
{
dire.Delete();
}
catch (IOException ex)
{ //Log ex.message
continue;
}
}
Moreover, I suggest you better use Path.Combine() instead of concatenating Strings.
You'll have to add try/catch blocks around the file deletion statement, so that your loops continue even if you get an exception. I would recommend logging the list of files which have thrown exceptions when you call delete.
If one of the files won't delete, the call to file.Delete() will throw an exception.
If you want to handle it, you must wrap it in a try/catch as follows:
foreach (FileInfo file in dir.GetFiles())
{
try
{
file.Delete();
}
catch (IOException exception)
{
// Here you should log the exception.Message
}
}