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.
Related
Assuming, that I have a long running file search, which is in the core just a recursive function as shown below (1M-100M files). If my process gets killed while still scanning for files or stops for whatever reason, is there a best practice way to implement a 'persistent state storage' or 'ContinueOnFailure'-Functionality?
Or am I completely on the wrong track and something like that is not even needed or needs a totally different approach?
Asking for any advice, also unrelated to a specific programming language (implemention will be in C#/F#, if possible) and please excuse the maybe false used terms here.
Further assumptions and thoughts.
Duplicates or few missing files are not a problem. Duplicates can be filtered and missing/'not up-to-date' files are to expect, as the operation happens on a living system. For an in-memory approach i could think of a dictionary that keeps track of the 'smallest depth' completed folders.
Or breaking down the problem be iterating till a certain threshold of subsets is reached and then keeping track of each subset in a database?
Also had a look at this. It this seems unpractical for larger network drives + i'm worried about the enumeration order?
let rec loop depth (someDir : DirectoryInfo) =
seq {
yield! someDir.EnumerateFiles ()
yield!
someDir.EnumerateDirectories ()
|> Seq.collect (loop (depth + 1))
}
let dir = DirectoryInfo "C:\\"
loop 0 dir
If you don't have permissions to enter sub-directories or permission to read the properties of a folder you need to use a recursive method to capture the exceptions and continue. See code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace SAveDirectoriesXml
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
const string FOLDER = #"c:\temp";
static XmlWriter writer = null;
static void Main(string[] args)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
writer = XmlWriter.Create(FILENAME, settings);
writer.WriteStartDocument(true);
DirectoryInfo info = new DirectoryInfo(FOLDER);
WriteTree(info);
writer.WriteEndDocument();
writer.Flush();
writer.Close();
Console.WriteLine("Enter Return");
Console.ReadLine();
}
static long WriteTree(DirectoryInfo info)
{
long size = 0;
writer.WriteStartElement("Folder");
try
{
writer.WriteAttributeString("name", info.Name);
writer.WriteAttributeString("numberSubFolders", info.GetDirectories().Count().ToString());
writer.WriteAttributeString("numberFiles", info.GetFiles().Count().ToString());
writer.WriteAttributeString("date", info.LastWriteTime.ToString());
foreach (DirectoryInfo childInfo in info.GetDirectories())
{
size += WriteTree(childInfo);
}
}
catch (Exception ex)
{
string errorMsg = string.Format("Exception Folder : {0}, Error : {1}", info.FullName, ex.Message);
Console.WriteLine(errorMsg);
writer.WriteElementString("Error", errorMsg);
}
FileInfo[] fileInfo = null;
try
{
fileInfo = info.GetFiles();
}
catch (Exception ex)
{
string errorMsg = string.Format("Exception FileInfo : {0}, Error : {1}", info.FullName, ex.Message);
Console.WriteLine(errorMsg);
writer.WriteElementString("Error",errorMsg);
}
if (fileInfo != null)
{
foreach (FileInfo finfo in fileInfo)
{
try
{
writer.WriteStartElement("File");
writer.WriteAttributeString("name", finfo.Name);
writer.WriteAttributeString("size", finfo.Length.ToString());
writer.WriteAttributeString("date", info.LastWriteTime.ToString());
writer.WriteEndElement();
size += finfo.Length;
}
catch (Exception ex)
{
string errorMsg = string.Format("Exception File : {0}, Error : {1}", finfo.FullName, ex.Message);
Console.WriteLine(errorMsg);
writer.WriteElementString("Error", errorMsg);
}
}
}
writer.WriteElementString("size", size.ToString());
writer.WriteEndElement();
return size;
}
}
}
I'm trying to list all folders and files in my User folder which is "Thomas", then I want to get all of the folders in those folders as well as files and so on. But whenever I run it, it throws this exception:
System.UnauthorizedAccessException: Access to the path 'C:\Users\Thomas\AppData\Local\Application Data' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileSystemEnumerableIterator`1.AddSearchableDirsToStack(SearchData localSearchData)
at System.IO.FileSystemEnumerableIterator`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.IO.Directory.GetDirectories(String path, String searchPattern, SearchOption searchOption)
at GetFilesInFolders.Program.Main(String[] args) in c:\users\thomas\documents\visual studio 2017\Projects\GetFilesInFolders\GetFilesInFolders\Program.cs:line 23
I find this strange since I have FULL permission to access this folder, but for some reason it says other-wise.
All of the code is below:
using System;
using System.IO;
using System.Collections.Generic;
namespace GetFilesInFolders
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter a path: ");
string path = Console.ReadLine();
int UnauthorizedAccessCount = 0;//counter for file i cant access
List<string> DirList = new List<string>();
List<string> FileList = new List<string>();
try
{
if (Directory.Exists(path))
{
foreach (string dir in Directory.GetDirectories(path, "*", SearchOption.AllDirectories))
{
DirList.Add(dir);
}
foreach (string file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
{
FileList.Add(file);
}
}
else
{
Console.WriteLine("Directory does not exist!");
Console.ReadKey();
return;
}
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("{0}", ex);
}
if(FileList.Count == 0)
{
Console.WriteLine("There were no files, or you didn't have proper permissions. (You didn't have permission to {0} files or folders", UnauthorizedAccessCount);
Console.ReadKey();
}
if(DirList.Count == 0)
{
Console.WriteLine("There were no folders, or you didn't have proper permissions. (You didn't have permission to {0} files or folders", UnauthorizedAccessCount);
Console.ReadLine();
}
else
{
Console.WriteLine("Here are all the folders:\n");
foreach (string dir in DirList)
{
Console.WriteLine(dir);
}
Console.WriteLine("Here are all the files:\n");
foreach (string file in FileList)
{
Console.WriteLine(file);
}
if (UnauthorizedAccessCount != 0)
{
Console.WriteLine("You had no permission to access {0} files.", UnauthorizedAccessCount);
}
else
{
}
Console.ReadLine();
}
}
}
}
You say you have full permission, but a console script does not run with the priviliges of the account. It runs with default user priviliges, and App Datais a restricted folder in Windows (where normal users are not supposed to poke around).
Change your console application to actually run as administrator. See this answer on how to do that:
How do I force my .NET application to run as administrator?
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;
}
}
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'm making a simple program where I'm trying to read through text files and count the number of occurrences of a specific phrase. These text files are in fact log files for my server, but anyhow the folder structure including my program is like
FailedReqLogFiles
....
LogFiles
folder1
textFile1
textFile2
folder2
textFile3
folder3
textFile4
textFile5
textFile6
wmsvg
....
MyProgram.exe
and I'm running
C:\inetpub\logs\MyProgram.exe "LogFiles" "somephrase"
from the Windows command line. The entire source code for my program is
using System;
using System.IO;
using System.Text.RegularExpressions;
class Test
{
static void Main(string[] args)
{
// args[1] = expression to search for, e.g. "cloudrealized-email-top-banner"
try
{
int count = 0;
string [] folders = System.IO.Directory.GetFiles(args[0]); // LogFiles subfolders, e.g. {"W3SVC1", "W3SVC3", "W3SVC5" , ... }
Console.Write("length of folder: {0}\n", folders.Length);
foreach (string thisfolder in folders)
{
string[] logs = System.IO.Directory.GetFiles(thisfolder);
foreach (string thislog in logs)
{
using (StreamReader sr = new StreamReader(args[0]))
{
String line = sr.ReadToEnd();
for (Match m = Regex.Match(line, args[1]); m.Success; m = m.NextMatch()) ++count;
}
}
}
Console.WriteLine("{0} currences of {1} found in log files", count, args[1]);
}
catch (Exception e)
{
Console.WriteLine("Error occured");
Console.WriteLine(e.Message);
}
}
}
and I can't figure out why it's not finding the files, as it keeps printing "length of folder: 0"
Is there any glaring problem with my program?
You're calling string [] folders = System.IO.Directory.GetFiles(args[0]);
Have you instead tried Directory.GetDirectories?
https://msdn.microsoft.com/en-us/library/c1sez4sc(v=vs.110).aspx