1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

C# help - File exists

Discussion in 'HTML, Graphics & Programming' started by AHarvey, Dec 3, 2018.

  1. AHarvey

    Sgarrista

    Joined: Mar 6, 2008

    Posts: 9,056

    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
     
  2. Bug One

    Sgarrista

    Joined: Oct 18, 2002

    Posts: 9,468

    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.
     
  3. Hades

    Capodecina

    Joined: Oct 19, 2002

    Posts: 20,869

    Location: Surrey and London

    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.
     
  4. AHarvey

    Sgarrista

    Joined: Mar 6, 2008

    Posts: 9,056

    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
     
  5. AHarvey

    Sgarrista

    Joined: Mar 6, 2008

    Posts: 9,056

    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: Dec 6, 2018 at 3:12 PM
  6. davetherave2

    Wise Guy

    Joined: Mar 27, 2003

    Posts: 2,480

    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".