Jaskier
Jaskier

Reputation: 1095

Reading specific files in different subfolders for same line of text C#

I'm currently creating a short Console Application to read a specific file within multiple subfolders. The file has the same name throughout all the directories, so moving them all to one directory and renaming them would be a huge hassle (there's well over 365 of these files. They are automatically created daily with a new name, and go back a few years). However, they're all under the same main folder.

I have looked into Read all files in directory sub folders. I understand I'm able to search through each individual subfolder and see all files (I was able to display their fileName to console for each one found in my foreach statement.

Code so far:

static void Main(string[] args)
{
    string readLine = string.Empty;
    var dir = new DirectoryInfo(@"C:\MotherDir\");
    // foreach loop to go through each subfolder to find FileINeed.txt
    foreach (var file in dir.EnumerateFiles("FileINeed.txt", SearchOption.AllDirectories))
    {
        //I get an error here: "System.IO.FileNotFoundException: 'Could not file file-'"
        using (StreamReader sr = new StreamReader(file.ToString()))   //this is using the wrong directory, not the one set previously (var dir)
        {
            while (!sr.EndOfStream)
            {
                readLine = sr.ReadLine();

                ProcessFiles(file.ToString());
            }
        }
    }

    Console.WriteLine("Finished.");
    Console.ReadKey(); //Gets pause at the end of the program
}

// Method to pass files through in order to search for specific string
static fileEntry ProcessFiles(string fileName)
{
    fileEntry inputFiles = new fileEntry();

    string fileString = string.Empty;
    string readLine;
    using (StreamReader sr = new StreamReader(fileName))
    {
        while (!sr.EndOfStream)
        {
            readLine = sr.ReadLine();

            if (readLine.Length < 1)
            {
            }

            if (readLine.Contains("RUN DATE: "))
            {
                Console.Write("RUN DATE:    ");
                Console.WriteLine(readLine);
            }
            if (readLine.Contains("1234567"))
            {
                Console.Write("Found this:    ");
                Console.WriteLine(readLine);
            }
            if (readLine.Contains("7654321"))
            {
                Console.Write("Found this:    ");
                Console.WriteLine(readLine);
            }
            if (readLine.Contains("1346785"))
            {
                Console.Write("Found this:    ");
                Console.WriteLine(readLine);
            }
            if (readLine.Contains("2589632"))
            {
                Console.Write("Found this:    ");
                Console.WriteLine(readLine);
            }
            if (readLine.Contains("12587412"))
            {
                Console.Write("Found this:    ");
                Console.WriteLine(readLine);
            }
        }
    }

    inputFiles.FileName = fileString;
    return inputFiles; 
}


public class fileEntry
{
    //stores file names and datetimes
    public string FileName { get; set; }

    public DateTime FileDate { get; set; }
}

I apologize for the awful if statements looking for a specific string, I was trying to use a switch/case statement but wasn't able to get it work.

I only need this to output to the console window if it found one of the strings (I'm aware I'm trying to output the whole readLine). The purpose of this program is to just see if these strings exist within the files being processed.

I'm still fairly new to C#, and this is one of my first worthwhile programs I have written from scratch. So I apologize for the poor coding practices (if any) as I'm still learning! If you have any suggestions or help, it would be greatly appreciated! Please let me know if I'm needing to clarify anything!

Thank you in advance!

Upvotes: 2

Views: 1246

Answers (4)

Cetin Basoz
Cetin Basoz

Reputation: 23807

You are unnecessarily using StreamReader there, you should just pass it to your ProcessFiles (not file.ToString() but file.FullName which is the full name and path of file - other is FileInfo object):

// foreach loop to go through each subfolder to find FileINeed.txt
foreach (var file in dir.EnumerateFiles("FileINeed.txt", SearchOption.AllDirectories))
{
    //I get an error here: "System.IO.FileNotFoundException: 'Could not file file-'"
            ProcessFiles(file.FullName);
}

Note: Hard to understand purpose of ProcessFiles. ie: Why do you return back files back as you process as a new class? You already have them in the point where you first get the list.

Note2: BTW using dir.EnumerateFiles or dir.GetFiles is a better choice than using Directory.GetFiles especially if you want to also filter on other file properties like (CreationDate, ModificationDate ...).

Another sample:

void Main()
{
    string[] searches = { "RUN DATE: ", "1234567", "7654321", "1346785", "2589632", "12587412"};

    var dir = new DirectoryInfo(@"C:\MotherDir\");
    var files = from fi in dir.GetFiles("FileINeed.txt", SearchOption.AllDirectories)
                let content = File.ReadAllText(fi.FullName)
                // sample filter
                // where fi.CreationTime >= DateTime.Now.AddDays(-3)
                where searches.Any(c => content.Contains(c))
                select fi;

    foreach (var file in files)
    {
        Console.WriteLine(file.FullName);
    }           
}

Upvotes: 4

Jihad Haddad
Jihad Haddad

Reputation: 640

I think it is your use of

file.ToString()

which I am not sure what it returns. To get a Stream from FileInfo you need to use

file.OpenText()

so your failing code will be

using (StreamReader sr = file.OpenText())

And your ProcessFiles could take a FileInfo instead of a string and you get this

static fileEntry ProcessFiles(FileInfo file)

If you want to get the full path of your file from FileInfo you can use

Path.Combine(file.DirectoryName, file.Name)

Upvotes: 0

Reinstate Monica Cellio
Reinstate Monica Cellio

Reputation: 26143

The thing that jumps out as wrong is that you're opening each file and passing the file contents to ProcessFiles, which actually expects a filename, not file contents. Try changing the main() method to this...

static void Main(string[] args)
{
    // this gets all matching files in a string array...
    string[] allfiles = Directory.GetFiles(@"C:\MotherDir\", "FileINeed.txt", SearchOption.AllDirectories);

    // parse the string array and call ProcessFiles for each one...
    foreach (var file in allfiles)
    {
        ProcessFiles(file);
    }

    Console.WriteLine("Finished.");
    Console.ReadKey(); //Gets pause at the end of the program
}

Upvotes: 2

Philip Smith
Philip Smith

Reputation: 2801

dir.EnumerateFiles returns a FileInfo object. Use the file.FullName property to get the fully qualified path name.

Upvotes: 0

Related Questions