Как извлечь каждое имя папки из пути? - PullRequest
57 голосов
/ 30 декабря 2008

Мой путь \\server\folderName1\another name\something\another folder\

Как извлечь имя каждой папки в строку, если я не знаю, сколько папок в пути и я не знаю имен папок?

Большое спасибо

Ответы [ 15 ]

90 голосов
/ 30 декабря 2008
string mypath = @"..\folder1\folder2\folder2";
string[] directories = mypath.Split(Path.DirectorySeparatorChar);

Edit: Это возвращает каждую отдельную папку в массиве каталогов. Вы можете получить количество возвращенных папок следующим образом:

int folderCount = directories.Length;
26 голосов
/ 30 декабря 2008

Это хорошо в общем случае:

yourPath.Split(@"\/", StringSplitOptions.RemoveEmptyEntries)

В возвращаемом массиве нет пустого элемента, если сам путь заканчивается (обратной) косой чертой (например, "\ foo \ bar \"). Однако вы должны быть уверены, что yourPath действительно каталог, а не файл. Вы можете узнать, что это такое, и компенсировать, если это такой файл:

if(Directory.Exists(yourPath)) {
  var entries = yourPath.Split(@"\/", StringSplitOptions.RemoveEmptyEntries);
}
else if(File.Exists(yourPath)) {
  var entries = Path.GetDirectoryName(yourPath).Split(
                    @"\/", StringSplitOptions.RemoveEmptyEntries);
}
else {
  // error handling
}

Я считаю, что это охватывает все основы, не будучи слишком педантичным. Он вернет string[], который вы можете перебрать с помощью foreach, чтобы получить каждый каталог по очереди.

Если вы хотите использовать константы вместо магической строки @"\/", вам нужно использовать

var separators = new char[] {
  Path.DirectorySeparatorChar,  
  Path.AltDirectorySeparatorChar  
};

и затем используйте separators вместо @"\/" в коде выше. Лично я нахожу это слишком многословным и, скорее всего, не буду этого делать.

9 голосов
/ 14 марта 2013

Я вижу твой метод Wolf5370 и поднимаю тебя.

internal static List<DirectoryInfo> Split(this DirectoryInfo path)
{
    if(path == null) throw new ArgumentNullException("path");
    var ret = new List<DirectoryInfo>();
    if (path.Parent != null) ret.AddRange(Split(path.Parent));
    ret.Add(path);
    return ret;
}

На пути c:\folder1\folder2\folder3 это возвращает

c:\

c:\folder1

c:\folder1\folder2

c:\folder1\folder2\folder3

В таком порядке

OR

internal static List<string> Split(this DirectoryInfo path)
{
    if(path == null) throw new ArgumentNullException("path");
    var ret = new List<string>();
    if (path.Parent != null) ret.AddRange(Split(path.Parent));
    ret.Add(path.Name);
    return ret;
}

вернется

c:\

folder1

folder2

folder3

9 голосов
/ 10 марта 2012

Понимаю, что это старый пост, но я наткнулся на него, глядя - в конце концов я решил добавить приведенную ниже функцию, поскольку она сортировала то, что я делал в то время, лучше, чем любой из вышеперечисленных:

private static List<DirectoryInfo> SplitDirectory(DirectoryInfo parent)
{
    if (parent == null) return null;
    var rtn = new List<DirectoryInfo>();
    var di = parent;

    while (di.Name != di.Root.Name)
    {
    rtn.Add(new DirectoryInfo(di));
    di = di.Parent;
    }
    rtn.Add(new DirectoryInfo(di.Root));

    rtn.Reverse();
    return rtn;
}
4 голосов
/ 02 октября 2015
public static IEnumerable<string> Split(this DirectoryInfo path)
{
    if (path == null) 
        throw new ArgumentNullException("path");
    if (path.Parent != null)
        foreach(var d in Split(path.Parent))
            yield return d;
    yield return path.Name;
}
4 голосов
/ 11 января 2013
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    /// <summary>
    /// Use to emulate the C lib function _splitpath()
    /// </summary>
    /// <param name="path">The path to split</param>
    /// <param name="rootpath">optional root if a relative path</param>
    /// <returns>the folders in the path. 
    ///     Item 0 is drive letter with ':' 
    ///     If path is UNC path then item 0 is "\\"
    /// </returns>
    /// <example>
    /// string p1 = @"c:\p1\p2\p3\p4";
    /// string[] ap1 = p1.SplitPath();
    /// // ap1 = {"c:", "p1", "p2", "p3", "p4"}
    /// string p2 = @"\\server\p2\p3\p4";
    /// string[] ap2 = p2.SplitPath();
    /// // ap2 = {@"\\", "server", "p2", "p3", "p4"}
    /// string p3 = @"..\p3\p4";
    /// string root3 = @"c:\p1\p2\";
    /// string[] ap3 = p1.SplitPath(root3);
    /// // ap3 = {"c:", "p1", "p3", "p4"}
    /// </example>
    public static string[] SplitPath(this string path, string rootpath = "")
    {
        string drive;
        string[] astr;
        path = Path.GetFullPath(Path.Combine(rootpath, path));
        if (path[1] == ':')
        {
            drive = path.Substring(0, 2);
            string newpath = path.Substring(2);
            astr = newpath.Split(new[] { Path.DirectorySeparatorChar }
                , StringSplitOptions.RemoveEmptyEntries);
        }
        else
        {
            drive = @"\\";
            astr = path.Split(new[] { Path.DirectorySeparatorChar }
                , StringSplitOptions.RemoveEmptyEntries);
        }
        string[] splitPath = new string[astr.Length + 1];
        splitPath[0] = drive;
        astr.CopyTo(splitPath, 1);
        return splitPath;
    }
3 голосов
/ 30 декабря 2008

Быстрый ответ - использовать метод .Split ('\\').

2 голосов
/ 30 декабря 2008

Может быть, вызвать Directory.GetParent в цикле? Это если вам нужен полный путь к каждому каталогу, а не только имена каталогов.

1 голос
/ 30 декабря 2008

Существует несколько способов представления пути к файлу. Вы должны использовать класс System.IO.Path для получения разделителей для ОС, так как он может варьироваться в зависимости от UNIX и Windows. Кроме того, большинство (или все, если я не ошибаюсь) .NET-библиотек принимает «\» или «/» в качестве разделителя пути, независимо от ОС. По этой причине я бы использовал класс Path, чтобы разделить ваши пути. Попробуйте что-то вроде следующего:

string originalPath = "\\server\\folderName1\\another\ name\\something\\another folder\\";
string[] filesArray = originalPath.Split(Path.AltDirectorySeparatorChar,
                              Path.DirectorySeparatorChar);

Это должно работать независимо от количества папок или имен.

0 голосов
/ 24 ноября 2018

Я только что написал это, так как не нашел ни одного уже встроенного в C #.

/// <summary>
/// get the directory path segments.
/// </summary>
/// <param name="directoryPath">the directory path.</param>
/// <returns>a IEnumerable<string> containing the get directory path segments.</returns>
public IEnumerable<string> GetDirectoryPathSegments(string directoryPath)
{
    if (string.IsNullOrEmpty(directoryPath))
    { throw new Exception($"Invalid Directory: {directoryPath ?? "null"}"); }

    var currentNode = new System.IO.DirectoryInfo(directoryPath);

    var targetRootNode = currentNode.Root;
    if (targetRootNode == null) return new string[] { currentNode.Name };
    var directorySegments = new List<string>();
    while (string.Compare(targetRootNode.FullName, currentNode.FullName, StringComparison.InvariantCultureIgnoreCase) != 0)
    {
        directorySegments.Insert(0, currentNode.Name);
        currentNode = currentNode.Parent;
    }
    directorySegments.Insert(0, currentNode.Name);
    return directorySegments;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...