How Path.GetDirectoryName Works?

23.7k views Asked by At

When i use OpenFileDialog to Open file, of course i need to get the file directory and its name to load the file.(to load xml, to access the file i need full path.)

opd is OpenFileDialog

        if (opd.ShowDialog() == true)
        {
            var names = opd.FileNames;

            foreach (string name in names)
            {
                LoadFile(Path.Combine(Path.GetDirectoryName(name), name));
            }
        }

my question is How Path.GetDirectoryName take the path of the File by Just taking the string ?

Path.GetDirectoryName(name)

name is Just string and this method takes its directory by just taking string? . there can be thousands of files with same name inside computer.

ShortQuestion: where is opd refrenced?

Edit:

i thought opd.FileNames just takes name of the files.(because of methods name)

and Also i found something interesting.

LoadFile(Path.Combine(Path.GetDirectoryName(name), name));

this works fine Because Path.Combine will just skip the same part of string.

Ex:

string name = @"C:\Users\Default\xml.xml";
string getDirNameResault= Path.GetDirectoryName(name);// this will be C:\Users\Default

So Path.Combine will be

 Path.Combine(@"C:\Users\Default", @"C:\Users\Default\xml.xml)

witch returns "C:\Users\Default\xml.xml" !

2

There are 2 answers

2
CodeCaster On BEST ANSWER

name is Just string and this method takes its directory by just taking string? . there can be thousands of files with same name inside computer.

name contains the full path, Path.GetDirectoryName() just strips everything after the last directory separator, Path.Combine(Path.GetDirectoryName(name), name) will not do anything useful:

If path2 includes a root, path2 is returned.

Just use name directly.

1
Nikolay Kostov On

Path.GetDirectoryName splits the string you already have (from opd) by slash / or \ and then returns everything except last part.

Complete source code of the function in .NET Core foundational libraries (called CoreFX) you can find here: https://github.com/dotnet/corefx/blob/41e203011152581a6c65bb81ac44ec037140c1bb/src/System.Runtime.Extensions/src/System/IO/Path.cs#L151

Code of the implementation:

// Returns the directory path of a file path. This method effectively
// removes the last element of the given file path, i.e. it returns a
// string consisting of all characters up to but not including the last
// backslash ("\") in the file path. The returned value is null if the file
// path is null or if the file path denotes a root (such as "\", "C:", or
// "\\server\share").
//
public static String GetDirectoryName(String path)
{
    if (path != null)
    {
        CheckInvalidPathChars(path);

#if FEATURE_LEGACYNETCF
        if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
        {
#endif

            string normalizedPath = NormalizePath(path, false);

            // If there are no permissions for PathDiscovery to this path, we should NOT expand the short paths
            // as this would leak information about paths to which the user would not have access to.
            if (path.Length > 0)
            {
                try
                {
                    // If we were passed in a path with \\?\ we need to remove it as FileIOPermission does not like it.
                    string tempPath = Path.RemoveLongPathPrefix(path);

                    // FileIOPermission cannot handle paths that contain ? or *
                    // So we only pass to FileIOPermission the text up to them.
                    int pos = 0;
                    while (pos < tempPath.Length && (tempPath[pos] != '?' && tempPath[pos] != '*'))
                        pos++;

                    // GetFullPath will Demand that we have the PathDiscovery FileIOPermission and thus throw 
                    // SecurityException if we don't. 
                    // While we don't use the result of this call we are using it as a consistent way of 
                    // doing the security checks. 
                    if (pos > 0)
                        Path.GetFullPath(tempPath.Substring(0, pos));
                }
                catch (SecurityException)
                {
                    // If the user did not have permissions to the path, make sure that we don't leak expanded short paths
                    // Only re-normalize if the original path had a ~ in it.
                    if (path.IndexOf("~", StringComparison.Ordinal) != -1)
                    {
                        normalizedPath = NormalizePath(path, /*fullCheck*/ false, /*expandShortPaths*/ false);
                    }
                }
                catch (PathTooLongException) { }
                catch (NotSupportedException) { }  // Security can throw this on "c:\foo:"
                catch (IOException) { }
                catch (ArgumentException) { } // The normalizePath with fullCheck will throw this for file: and http:
            }

            path = normalizedPath;

#if FEATURE_LEGACYNETCF
        }
#endif

        int root = GetRootLength(path);
        int i = path.Length;
        if (i > root)
        {
            i = path.Length;
            if (i == root) return null;
            while (i > root && path[--i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar) ;
            String dir = path.Substring(0, i);
#if FEATURE_LEGACYNETCF
            if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
            {
                if (dir.Length >= MAX_PATH - 1)
                    throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
            }
#endif
            return dir;
        }
    }
    return null;
}

For the complete source code of the function (in Mono) see here: https://github.com/mono/mono/blob/master/mcs/class/corlib/System.IO/Path.cs#L199