C# help - File exists

Soldato
Joined
6 Mar 2008
Posts
10,078
Location
Stoke area
Hi all,

We've an issue at work that it appear some staff are incapable of reading a process and checking files exists, so i'm knocking something up quick:

Code:
Console.WriteLine(file_date);
         
            if (File.Exists(@t1_directory_sent1 + "acbd_1234_" + file_date + ".txt"))
            {
                Console.WriteLine("acbd_1234_" + file_date + ".txt - " + "The file exists.");
            }
            if (File.Exists(@t1_directory_sent1 + "acbd_1234_" + file_date + ".aud"))
            {
                Console.WriteLine("acbd_1234" + file_date + ".aud - " + "The file exists.");
            }

If it was just these 2 that'd be easy but in total we've a total of around 53 files to check. They could be in 1 of 3 locations, have txt, aud, gpg and csv file extensions.

Some also have a file_date of yyyyMMdd and some yyyyMMdd HHMMSS so I'll need to wildcard those ones.

Can anyone suggest a quicker way of doing this without manually typing them all out?

Obviously, a simple loop through but I'm unsure how to store all the variations to get this to function as expected.

Thanks
 
Soldato
Joined
18 Oct 2002
Posts
13,998
Location
Sandwich, Kent
I'd get the directory into a list, then enumerate through the list to see if any of the items contains the string(s) I'm looking to match.
Then if it does, use path.getextension to get the extension, substring if I want to pull out a date (hard to say without knowing exactly your proposed file format), to add to the string being returned.

Also, instead of returning a line - I'd build an array of strings, so I could perform the check, then return the results and a count at the end.
 
Man of Honour
Joined
19 Oct 2002
Posts
29,509
Location
Surrey
I'd probably consider two ways. Firstly you could build an array of files above and then iterate through them looking for a name which matches the pattern. Or secondly you could iterate around a list of files and look for them in each of the directories. Either way this should be done programmatically rather than explicitly looking for a specific file. Don't hard code the files in the code. I would strongly suggest holding three reference data files (or a single file with three sections) containing:

1) A list of directories to check.
2) A list of file suffixes to check.
3) A list of file prefixed to check.

For example config file 2 would contain 'txt, aud, gpg, csv, etc'. Config file 3 could contain the first part of the file such as 'acbd_1234', etc. You would then programmatically look in each of the directories for a file which looks like acbd_1234.*.txt, acbd_1234*.gpg, acbd_1234*.csv, etc. If it's essential to check the date in the filename is correct then once you find the file you just check it against a known date format.
 
Soldato
OP
Joined
6 Mar 2008
Posts
10,078
Location
Stoke area
Managed to make it a little more elegant and easier to read.

Basically, there are 2 teams receiving 4 chunks of extracts from 2 different places, each place has a storage and a sent area, so 4 areas in total.

Each of the 4 directories into a variable for each one.
there are 4 lists, 3 for file names, 1 for a filename that only runs on a Thursday
4 loops that go through the data and output whether it's in location 1, location 2 or hasn't been created/sent
A counter to show the total number of files in the lists vs the total sent / not sent


under 300 line of code, not too bad for my 2nd c# console app
 
Soldato
OP
Joined
6 Mar 2008
Posts
10,078
Location
Stoke area
Ok, my Thursday files are different format: ABCD_Q1_YYYYMMDD_HHMMSS.CSV

Code:
            List<string> filesThurs = new List<string>();
            filesThurs.Add("ABCD_Q1_" + file_date + ?? + ".csv");
            filesThurs.Add("ABCD_Q2_" + file_date + ?? + ".csv");
            filesThurs.Add("ABCD_Q3_" + file_date + ?? + ".csv");
            filesThurs.Add("ABCD_Q4_" + file_date + ?? + ".csv");
            filesThurs.Add("ABCD_Q5_" + file_date + ?? + ".csv");

So, I need to add a wildcard to each add.

I'd seen a webpage a few days ago where substituting the ?? for the * wildcard but I can't get it to work.

Am I going to be better just using the "filesThurs.Add("ABCD_Q1_" + file_date);" and then adding the wild card during the loop looking in the directory or can this be done as part of the add to the lists? I'm thinking it's the first option but wanted clarification from those with more experience (so most people :D )

A job for Regex? seeing it mentioned a lot on searches, something new to learn

It seems that File.Exists can't be used with wildcards, new approach needed
 
Last edited:
Soldato
Joined
27 Mar 2003
Posts
2,708
So this is an interesting little problem. Here is something that I have quickly knocked up for you that may be similar or not to what you have produced already. I have taken a slightly different approach to the file/path locations and assume at the moment you would be running this on the server/servers that have this data.

The first thing I have setup is a json file with some config settings:
json1.json
Code:
{
  "drives": ["C", "D"],
  "directories": [ "Program Files","AMD" ],
  "filenames": ["test", "qwerty*", "*"],
  "filetypes": [ ".xlsx", ".csv", ".log" ],
  "subScanning": true
}

then the main program file is like this:

Code:
 class Program
    {
        static void Main(string[] args)
        {

            var fileConfig = new FileConfig();

            var jsonCOnfig = File.ReadAllText(@"json1.json");

            fileConfig = JsonConvert.DeserializeObject<FileConfig>(jsonCOnfig);

            var returnObject = new Dictionary<string, List<string>>();

            if (fileConfig != null && fileConfig.Drives.Count > 0)
            {
                foreach (var pathCheck in fileConfig.GetPathsToCheck())
                {
                    if (Directory.Exists(pathCheck))
                    {
                        Console.WriteLine(string.Format(@"Path Exists so going to check files:: {0}", pathCheck));
                        foreach (var filename in fileConfig.GetFileNamesWithExtensions())
                        {


                            SearchOption option = fileConfig.SubScanning ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
                            var directory = new DirectoryInfo(pathCheck);

                            Console.WriteLine(string.Format(@"Currently Searching for the following File(s):: {0}, {1}", pathCheck, filename));
                            try
                            {
                                var results = directory.GetFiles(filename, option).ToList();


                                Console.WriteLine(string.Format("Found a total of::  {0} file(s) with this search pattern", results.Count));

                                returnObject.Add(string.Format(@"{0}{1}", pathCheck, filename).Replace(@"\\", @"\"), results.Select(s => Path.GetFullPath(s.FullName)).ToList());
                            }
                            catch (Exception error)
                            {
                                Console.WriteLine(string.Format("Sorry seems we encountered an error accessing this folder.The message returned was::{0}", error.Message));
                                returnObject.Add(string.Format(@"{0}{1}", pathCheck, filename), new List<string>());
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine(string.Format(@"Sorry seems this directory:: {0} doesn't exist", pathCheck));
                    }
                }

                if (returnObject.Count > 0)
                {
                    Console.WriteLine(string.Format("Results Found Based on your criteria:: {0}", JsonConvert.SerializeObject(returnObject)));
                }

                var stream = new StreamWriter(string.Format("Results Scan-{0}-{1}.json", Guid.NewGuid(), DateTime.Now.ToString("yyyyMMdd")));
                stream.WriteLine(JsonConvert.SerializeObject(returnObject));
                stream.Close();

            }
            else
            {
                Console.WriteLine("Sorry seems you have not loaded the correct settings for this to run. ");
            }
            Console.ReadKey();
        }
    }

    public class FileConfig
    {
        public List<string> Drives { get; set; }
        public List<string> Directories { get; set; }
        public List<string> FileNames { get; set; }
        public List<string> FileTypes { get; set; }

        public bool SubScanning { get; set; }


        public FileConfig()
        {
            Drives = new List<string>();
            Directories = new List<string>();
            FileNames = new List<string>();
            FileTypes = new List<string>();
            SubScanning = true;
        }


        public List<string> GetPathsToCheck()
        {
            List<string> model = new List<string>();

            foreach (var drive in Drives)
            {
                StringBuilder builder = new StringBuilder();


                if (Directories.Count > 0)
                {
                    foreach (var directory in Directories)
                    {
                        model.Add(string.Format(@"{0}:\{1}\", drive, directory));
                    }
                }
                else
                {
                    model.Add(string.Format(@"{0}:\", drive));
                }



            }




            return model;
        }


        public List<string> GetFileNamesWithExtensions()
        {
            List<string> model = new List<string>();

            if (FileNames.Count > 0)
            {
                foreach (var filename in FileNames)
                {
                    if (FileTypes.Count > 0)
                    {
                        foreach (var filetype in FileTypes)
                        {
                            model.Add(string.Format("{0}{1}{2}", filename, filetype.Contains(".") ? string.Empty : ".", filetype));

                        }
                    }
                    else
                    {
                        model.Add(string.Format("{0}.*", filename));
                    }


                }
            }
            else
            {
                //no file names so just do extension checking

                if (FileTypes.Count > 0)
                {
                    foreach (var filetype in FileTypes)
                    {
                        model.Add(string.Format("*{0}{1}", filetype.Contains(".") ? string.Empty : ".", filetype));

                    }
                }
                else
                {
                    //just default to find all files.
                    model.Add("*.*");
                }
            }



            return model;

        }


    }


In order for this to work I have included the NewtonSoft Json nuget package for handling the serializing and deserializing or objects to/from files.

This would then simply just run and then build up a "tree" for you to scan the files/folders you specify in your json config and build a results file like this:

Code:
{
  "C:\\Program Files\\\\test.xlsx": [],
  "C:\\Program Files\\\\test.csv": [],
  "C:\\Program Files\\\\test.log": [],
  "C:\\Program Files\\\\qwerty*.xlsx": [],
  "C:\\Program Files\\\\qwerty*.csv": [],
  "C:\\Program Files\\\\qwerty*.log": [],
  "C:\\Program Files\\\\*.xlsx": [],
  "C:\\Program Files\\\\*.csv": [
    {
      "OriginalPath": "dotnet-supported-package-versions.csv",
      "FullPath": "C:\\Program Files\\dotnet\\sdk\\1.1.11\\dotnet-supported-package-versions.csv"
    },
    {
      "OriginalPath": "dotnet-supported-package-versions.csv",
      "FullPath": "C:\\Program Files\\dotnet\\sdk\\1.1.8\\dotnet-supported-package-versions.csv"
    },
    {
      "OriginalPath": "dotnet-supported-package-versions.csv",
      "FullPath": "C:\\Program Files\\dotnet\\sdk\\1.1.9\\dotnet-supported-package-versions.csv"
    }
  ],
  "C:\\Program Files\\\\*.log": [
    {
      "OriginalPath": "edpa0.log",
      "FullPath": "C:\\Program Files\\Manufacturer\\Endpoint Agent\\edpa0.log"
    },
    {
      "OriginalPath": "edpa_ext0.log",
      "FullPath": "C:\\Program Files\\Manufacturer\\Endpoint Agent\\edpa_ext0.log"
    },
    {
      "OriginalPath": "edpa_ext1.log",
      "FullPath": "C:\\Program Files\\Manufacturer\\Endpoint Agent\\edpa_ext1.log"
    },
    {
      "OriginalPath": "FlexResponse0.log",
      "FullPath": "C:\\Program Files\\Manufacturer\\Endpoint Agent\\OperationLogs\\FlexResponse0.log"
    },
    {
      "OriginalPath": "uninstall.log",
      "FullPath": "C:\\Program Files\\VideoLAN\\VLC\\uninstall.log"
    }
  ],
  "C:\\AMD\\\\test.xlsx": [],
  "C:\\AMD\\\\test.csv": [],
  "C:\\AMD\\\\test.log": [],
  "C:\\AMD\\\\qwerty*.xlsx": [],
  "C:\\AMD\\\\qwerty*.csv": [],
  "C:\\AMD\\\\qwerty*.log": [],
  "C:\\AMD\\\\*.xlsx": [],
  "C:\\AMD\\\\*.csv": [],
  "C:\\AMD\\\\*.log": [
    {
      "OriginalPath": "atikmdag_dce.log",
      "FullPath": "C:\\AMD\\atikmdag_dce.log"
    }
  ]
}


Happy to explain what I have done to make anything clear for you if you need it or provide the sample project I built so you can see it in action. This could be easily tweaked to include more complex rules such as regex's etc it just depends on how often this thing is going to be run and what your specific requirements are?

Hopefully you can see in this sample I have provided it contains wildcard checking in filenames for you so if you know the basic structure of the expected filenames it will hunt them out for you. Then all you need to do is change the config file rather than the "scanning engine".
 
Soldato
Joined
19 Oct 2008
Posts
5,949
Note that in C# I think 2015 or greater you can use string interpolation
Console.WriteLine("acbd_1234" + file_date + ".aud - " + "The file exists.");

Without checking this in the ide:
Console.WriteLine($"acbd_1234{file_date}.aud - The file exists.");
 
Back
Top Bottom