9
\$\begingroup\$

I have a Windows program that prompts the user to input a file path and filename. I then check that the file exists with Directory.Exists. Then the user inputs a filename and I check it using this answer to check whether the filename is valid or not (it may or may not yet exist).

using System;
using System.IO;
using System.Text.RegularExpressions;

public static string GetFilePath()
{
    string filePath = " ";
    bool directoryFound = true;
    do
    {
        if (!directoryFound)
        {
            Console.WriteLine("This directory not found:\n{0}\nPlease double check file path. \nPlease Double check that this program has read and write access to the directory.\n", filePath);
        }

        Console.WriteLine("Please specify file location:");
        filePath = @Console.ReadLine(); 
        Console.Clear();

        directoryFound = Directory.Exists(filePath);
        if (filePath.Length >= 240) //This looks like a bad solution
        {
            directoryFound = false;
            Console.WriteLine("Please keep the filepath under 240 chars so that you still are able to provide a name for the file.");
        }

    } while (!directoryFound);

    filePath = GetFileName(filePath);

    return filePath ;
}

    public static string GetFileName(string filePath)
    {
        string fileName = " ";
        bool isValidName = true;
        int fileNameMaxLength = 0;
        do
        {
            if (!isValidName)
            {

                Console.WriteLine("{0} \nis not a valid filename. Make sure you enter a valid filename.\nYour max filename length should be {1}", fileName, fileNameMaxLength);
            }

            Console.WriteLine("Please enter the name of the file:");
            fileName = Console.ReadLine();
            Console.Clear();

            string illegalChars = @"^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$";

            isValidName = Regex.IsMatch(fileName, illegalChars, RegexOptions.CultureInvariant);

            if (fileName.Length + filePath.Length > 254) //254 instead of 260 in order to account for file extension
            {
                isValidName = false;
                fileNameMaxLength = 254 - filePath.Length;
            }

        } while (!isValidName);
        return Path.Combine(filePath, (fileName + ".ppm"));
    }

}

How could I make this be more elegant? I especially don't like:

if(filePath.Length >= 240)

I need to make sure that:

  • The filepath exists
  • The filename is valid
  • That filename + filepath <= 260 (this is max char limit on Windows)
  • That my program doesn't crash while doing this
\$\endgroup\$
  • \$\begingroup\$ The regexp does not catch all invalid filenames, e.g. with "<>" chars. \$\endgroup\$ – Andrew Savinykh May 21 at 4:39
12
\$\begingroup\$

For the if(filePath.Length >= 240) part, you can use the Path object. It throws a PathTooLongException.

You can then change to this :

try
{
    filePath = Path.GetFullPath(filePath);
}
catch (PathTooLongException ex)
{
    directoryFound = false;
    Console.WriteLine("Please keep the filepath under 240 chars so that you still are able to provide a name for the file.");
}

Note : you can find references to Path object here and see all exception you have to handle invalid path input.

Now for GetFileName(), you can use the same object Path.GetFileName(). It will check if the name is valid.

ArgumentException : path contains one or more of the invalid characters defined in GetInvalidPathChars.

...
fileName = Console.ReadLine();
            Console.Clear();
try
{
    fileName = Path.GetFileName(fileName);
}
catch (ArgumentException ex)
{
    // Whatever exception handling you want.
}

Note : Since you have to check more than one time if the Path is valid, I would create a method to do this.

public static bool PathIsValid(string inputPath)
{
    try
    {
        Path.GetFullPath(inputPath);
    }
    catch(PathTooLongException ex)
    {
        return false;
    }
    return true;
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I like this, thanks. It's frowned upon to use exceptions for validation, but in this case it's about the only certain way to determine path validity. Besides, how often does any code have to check a file path? In well written code, it should be a rare task, normally. \$\endgroup\$ – ProfK Jan 14 '17 at 6:03

Not the answer you're looking for? Browse other questions tagged or ask your own question.