简体   繁体   English

从文件路径中删除“head”目录

[英]Remove the 'head' directory from a file path

In .NET (VB or C#) Does anyone know a simple way to remove the 'head' directory from a file path String, meaning if I have path that looks something like this: Directory1/Directory2/Directory3 I want to get Directory2/Directory3 back. 在.NET(VB或C#)中是否有人知道从文件路径String中删除'head'目录的简单方法,这意味着如果我的路径看起来像这样: Directory1/Directory2/Directory3我想获取Directory2/Directory3背部。 I know there are some ways to do it, like split it into an array, and then starting with the second element concatenate it all back, I just feel like that, that's its an extremely inefficient way of doing it and was wondering if there is a better way to do this. 我知道有一些方法可以做到这一点,比如将它拆分成一个数组,然后从第二个元素开始将它连接起来,我只是觉得这样,这是一种非常低效的方法,并且想知道是否有一个更好的方法来做到这一点。

It depends on what you're looking for. 这取决于你在寻找什么。 If you know that things are in the form dir1/dir2/dir3/dir4... , then you can just look for the first / and take everything after that: 如果您知道dir1/dir2/dir3/dir4...形式的东西,那么您可以只查找第一个/并在此之后采取一切:

string dir = "dir1/dir2/dir3";
var pos = dir.IndexOf('/');
if (pos != -1)
{
    result = dir.Substring(pos+1);
}

If you can also accept full path names of the form c:\\dir\\dir\\file.ext or \\\\server\\dir\\dir\\file.ext , then you'll probably want to make sure that you make any relative paths into full paths first. 如果你也可以接受c:\\dir\\dir\\file.ext\\\\server\\dir\\dir\\file.ext形式的完整路径名,那么你可能想要确保你做任何相对路径首先是完整路径。 Then use the methods in the System.IO.Path class to extract the drive or server names before using something like the IndexOf trick above. 然后使用System.IO.Path类中的方法在使用类似上面的IndexOf技巧之前提取驱动器或服务器名称。

Look at the System.IO.Path class. 查看System.IO.Path类。 It has a number of useful methods for this kind of thing. 对于这种事情,它有许多有用的方法。

For example, you might use it's GetPathRoot() method as part of a call to String.Replace() like so: 例如,您可以使用它的GetPathRoot()方法作为对String.Replace()的调用的一部分,如下所示:

public string RemoveHead(string path)
{
    return path.Replace(Path.GetPathRoot(path), "");
}

I don't have Visual Studio handy, so that likely needs some tweaks to account for separator characters or Drive letters, but it should give you the idea. 我没有Visual Studio方便,所以可能需要一些调整来解释分隔符或驱动器号,但它应该给你的想法。

If you want correctness and efficiency, 如果你想要正确和高效,

string path=@"dir1/dir2/dir3";
path=path.Substring(path.IndexOf(System.IO.Path.DirectorySeparatorChar)+1);

only 1 new string is created. 只创建了一个新字符串。

        /// <summary>
    /// Removes head.
    /// </summary>
    /// <param name="path">The path to drop head.</param>
    /// <param name="retainSeparator">If to retain separator before next folder when deleting head.</param>
    /// <returns>New path.</returns>
    public static string GetPathWithoutHead (string path, bool retainSeparator = false)
    {
        if (path == null) 
        {
            return path;
        }
        if (string.IsNullOrWhiteSpace (path)) 
        {
             throw new ArgumentException(path, "The path is not of a legal form.");
        }

        var root = System.IO.Path.GetPathRoot (path);
        if (!string.IsNullOrEmpty(root) && !StartsWithAny(root,System.IO.Path.DirectorySeparatorChar,System.IO.Path.AltDirectorySeparatorChar))
        {               
            return path.Remove(0,root.Length);
        }

        var sep = path.IndexOf(System.IO.Path.DirectorySeparatorChar);
        var altSep = path.IndexOf(System.IO.Path.AltDirectorySeparatorChar);
        var pos = MaxPositiveOrMinusOne (sep, altSep);
        if (pos == -1)
        {
            return string.Empty;
        }

        if (pos == 0) 
        {
            return GetPathWithoutHead(path.Substring(pos+1), retainSeparator);
        }

        var eatSeparator = !retainSeparator ? 1 : 0;
        return path.Substring(pos+eatSeparator);
    }

    /// <summary>
    /// Startses the with.
    /// </summary>
    /// <returns><c>true</c>, if with was startsed, <c>false</c> otherwise.</returns>
    /// <param name="val">Value.</param>
    /// <param name="maxLength">Max length.</param>
    /// <param name="chars">Chars.</param>
    private static bool StartsWithAny(string value, params char[] chars)
    {
        foreach (var c in chars) 
        {
            if (value[0] == c) 
            {
                return true;
            }
        }
        return false;
    }

    /// <summary>
    /// Maxs the positive or minus one.
    /// </summary>
    /// <returns>The positive or minus one.</returns>
    /// <param name="val1">Val1.</param>
    /// <param name="val2">Val2.</param>
    private static int MaxPositiveOrMinusOne(int val1, int val2)
    {
        if (val1 < 0 && val2 < 0)
        {
            return -1;
        }
        return Math.Max(val1,val2: val2);
    }

Several unit tests are here 这里有几个单元测试

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM