Question

I'm writing a C# program that uses System.IO methods to work with files and directories. Some of these methods include Directory.GetDirectories, Directory.GetFiles, and Path.GetDirectoryName which can all throw the PathTooLongException exception if the path is too long. My first question is does the Microsoft .NET Framework enforce the maximum length of a path, the same way that a call to a Windows API in C++ does? Does a path (in a string) in C# that exceeds MAX_PATH cause PathTooLongException to be thrown?

Should I use this?

string getFolderName(string path) 
{
    if (string.IsNullOrWhiteSpace(path))
        return string.Empty;

    if (path.Length > 260)
    {
        System.Diagnostics.Debug.WriteLine("Path is too long.");
        return string.Empty;
    }

    string folderName = System.IO.Path.GetDirectoryName(path);

    return folderName;
}

Or this?

string getFolderName(string path) 
{
    if (string.IsNullOrWhiteSpace(path))
        return string.Empty;

    string folderName = string.Empty;

    try {
        folderName = System.IO.Path.GetDirectoryName(path);
    }
    catch (System.IO.PathTooLongException)
    {
        System.Diagnostics.Debug.WriteLine("Path is too long.");
    }

    return folderName;
}
Était-ce utile?

La solution

Better is a judgment call.

Catching an exception is a much slower operation than testing for the condition and avoiding the exception entirely. However, unless you are going to encounter a large number of exceptions, the performance difference is simply not important.

It is hard too imagine a case where you would get large numbers of path too long errors, unless you are trying to do something where are copying or moving tree into a directory node that is already deep. In which case, you are probably better off to test everthing up front so you don't create a large slow operation that will fail in the middle.

However, a hard-coded 260 is a bad idea anyway as this previous answer shows.

There is no built-in windows function that gives the real answer for a given system, but you could simply determine the answer by trial and error (maybe a binary search) on the user system before starting your operations.

However, if you read the article I referenced, you will see that you can easily create longer paths in a program than will work well in windows. Windows explorer has problems once you reach 255 characters, so long story short, I would recommend a limit of 255 at most if you have any choice in the matter.

Autres conseils

Hard-coding values into code is typically not the best idea. As an FYI, the the directory name must be less than 248 characters and the maximum filename length must be less than 260 characters. If you are looking specifically for paths that are too long, your existing code already has a hole.

This question addresses the issue and provides some solutions. If you want to use a fixed length for the path, you could do something like

public static bool IsPathWithinLimits (string fullPathAndFilename)
{
     const int MAX_PATH_LENGTH = 259;//260-1
     return fullPathAndFilename.Length<=MAX_PATH_LENGTH;
}

You could also use reflection to find the maximum path length. I would use reflection to get the maximum path length ONCE and then store that variable and use it on subsequent calls.

public class PathHelper
{
     private static int MaxPathLength {get; set;}

     static PathHelper()
     {
          // reflection
          FieldInfo maxPathField = typeof(Path).GetField("MaxPath", 
              BindingFlags.Static | 
              BindingFlags.GetField | 
              BindingFlags.NonPublic );

          // invoke the field gettor, which returns 260
          MaxPathLength = (int) maxPathField.GetValue(null);
         //the NUL terminator is part of MAX_PATH https://msdn.microsoft.com/en-us/library/aa365247.aspx#maxpath
               MaxPathLength--; //So decrease by 1

     }


     public static bool IsPathWithinLimits (string fullPathAndFilename)
     {          
          return fullPathAndFilename.Length<=MaxPathLength;
     }

}

Note: This code has not been tested.

I think the fact that you are unsure of how MAX_PATH is used under the hood suggests that it would be better to catch the exception rather than trying to perform the check yourself.

My general philosophy is that the code that is actually using a piece of data should be the one responsible for checking that it's valid. Since your getFolderName method doesn't do anything with path other than pass it to GetDirectoryName I would not bother checking the length and probably wouldn't even bother checking that it's empty/null. Just pass it along and let GetDirectoryName worry about it.

There are, of course, exceptions to this rule. If, for example, I had a method that took in a bunch of parameters and then passed those parameters to various other methods, I may want to perform some checking up front so that I don't end up in some weird state because only half the parameters were valid.

As a side note, I believe C# (maybe all of .NET) automatically initializes all variables to their default value, so initializing folderName to String.Empty is redundant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top