如何确保路径中有尾随目录分隔符?

pit*_*arx 47 .net c# path

我遇到了问题AppDomain.CurrentDomain.BaseDirectory.

有时路径以'\'结束,有时则不以.我找不到合理的理由.

如果我使用它会没事,Path.Combine但我想做Directory.GetParent,它产生不同的结果.

你有没有发现这个问题?

我可以以不同的方式获取应用程序的父目录吗?

我目前的黑客是:

var baseDir = AppDomain.CurrentDomain.BaseDirectory;
if (!baseDir.EndsWith("\\")) baseDir += "\\";
Run Code Online (Sandbox Code Playgroud)

Han*_*ney 54

您可以使用TrimEnd轻松确保所需的行为:

var baseDir = AppDomain.CurrentDomain.BaseDirectory.TrimEnd('\\') + "\\";
Run Code Online (Sandbox Code Playgroud)

为了获得最佳效率(通过避免额外分配),检查字符串是否\在更改之前没有结束,因为您并不总是需要:

var baseDir = AppDomain.CurrentDomain.BaseDirectory;
if (!baseDir.EndsWith("\\"))
{
    baseDir += "\\";
}
Run Code Online (Sandbox Code Playgroud)

  • 要使其跨平台,您可以使用Path.DirectorySeparatorChar替换\\ (23认同)
  • @Rots:`TrimEnd`调用也应包括`AltDirectorySeparatorChar` (5认同)

Adr*_*tti 38

就像那样,只是保持你的黑客.

普通的 Win32中,有一个辅助函数PathAddBackslash.只需与目录分隔符保持一致:检查Path.DirectorySeparatorCharPath.AltDirectorySeparatorChar不是硬编码\.

这样的事情(请注意没有严重的错误检查):

string PathAddBackslash(string path)
{
    // They're always one character but EndsWith is shorter than
    // array style access to last path character. Change this
    // if performance are a (measured) issue.
    string separator1 = Path.DirectorySeparatorChar.ToString();
    string separator2 = Path.AltDirectorySeparatorChar.ToString();

    // Trailing white spaces are always ignored but folders may have
    // leading spaces. It's unusual but it may happen. If it's an issue
    // then just replace TrimEnd() with Trim(). Tnx Paul Groke to point this out.
    path = path.TrimEnd();

    // Argument is always a directory name then if there is one
    // of allowed separators then I have nothing to do.
    if (path.EndsWith(separator1) || path.EndsWith(separator2))
        return path;

    // If there is the "alt" separator then I add a trailing one.
    // Note that URI format (file://drive:\path\filename.ext) is
    // not supported in most .NET I/O functions then we don't support it
    // here too. If you have to then simply revert this check:
    // if (path.Contains(separator1))
    //     return path + separator1;
    //
    // return path + separator2;
    if (path.Contains(separator2))
        return path + separator2;

    // If there is not an "alt" separator I add a "normal" one.
    // It means path may be with normal one or it has not any separator
    // (for example if it's just a directory name). In this case I
    // default to normal as users expect.
    return path + separator1;
}
Run Code Online (Sandbox Code Playgroud)

为什么这么多代码?小学,因为如果用户输入/windows/system32你不想得到,/windows/system32\/windows/system32/魔鬼在细节...

以更好的自我解释形式将所有内容组合在一起:

string PathAddBackslash(string path)
{
    if (path == null)
        throw new ArgumentNullException(nameof(path));

    path = path.TrimEnd();

    if (PathEndsWithDirectorySeparator())
        return path;

    return path + GetDirectorySeparatorUsedInPath();

    bool PathEndsWithDirectorySeparator()
    {
        if (path.Length == 0)
            return false;

        char lastChar = path[path.Length - 1];
        return lastChar == Path.DirectorySeparatorChar
            || lastChar == Path.AltDirectorySeparatorChar;
    }

    char GetDirectorySeparatorUsedInPath()
    {
        if (path.Contains(Path.AltDirectorySeparatorChar))
            return Path.AltDirectorySeparatorChar;

        return Path.DirectorySeparatorChar;
    }
}
Run Code Online (Sandbox Code Playgroud)

file://即使看起来如此,也不会处理URI格式.在正确的事情又是做什么其他的.NET I/O功能的更多信息:不处理这种格式(也可能抛出一个异常).

作为替代方案,您始终可以导入W​​in32功能:

[DllImport("shlwapi.dll", 
    EntryPoint = "PathAddBackslashW",
    SetLastError = True,
    CharSet = CharSet.Unicode)]
static extern IntPtr PathAddBackslash(
    [MarshalAs(UnmanagedType.LPTStr)]StringBuilder lpszPath);
Run Code Online (Sandbox Code Playgroud)

  • @pitermarx实际上我们甚至不确定FileCopy的作用!一个_system_函数IMO总是一个不错的选择,至少它会为你处理任何变化(并且它总是会尊重它的合同:添加一个尾随反斜杠).当然,并非总是它们是完美的解决方案...... (4认同)

Pau*_*oke 6

我经常用

path = Path.Combine(path, "x");
path = path.Substring(0, path.Length - 1);
Run Code Online (Sandbox Code Playgroud)

或者,如果我在同一个项目中不止一次或两次需要这个,我可能会使用这样的辅助函数:

string EnsureTerminatingDirectorySeparator(string path)
{
    if (path == null)
        throw new ArgumentNullException("path");

    int length = path.Length;
    if (length == 0)
        return "." + Path.DirectorySeparatorChar;

    char lastChar = path[length - 1];
    if (lastChar == Path.DirectorySeparatorChar || lastChar == Path.AltDirectorySeparatorChar)
        return path;

    int lastSep = path.LastIndexOfAny(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });
    if (lastSep >= 0)
        return path + path[lastSep];
    else
        return path + Path.DirectorySeparatorChar;
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*s T 6

从 .NET Core 3.0 开始,Path.EndsInDirectorySeparator()可以使用:

string baseDir = AppDomain.CurrentDomain.BaseDirectory;

if (!Path.EndsInDirectorySeparator(baseDir))
{
    baseDir += Path.DirectorySeparatorChar;
}
Run Code Online (Sandbox Code Playgroud)

对于Unix,它检查最后一个是否char'/'.

对于Windows,它检查最后一个是否char是文字'\''/'.


Bac*_*ata 5

为了获得跨平台支持,可以使用以下代码段:

using System.IO;

// Your input string.
string baseDir = AppDomain.CurrentDomain.BaseDirectory;

// Get the absolut path from it (in case ones input is a relative path).
string fullPath = Path.GetFullPath(baseDir);

// Check for ending slashes, remove them (if any)
// and add a cross platform slash at the end.
string result = fullPath
                    .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
                    + Path.DirectorySeparatorChar;
Run Code Online (Sandbox Code Playgroud)

作为一种方法:

private static string GetFullPathWithEndingSlashes(string input)
{
    string fullPath = Path.GetFullPath(input);

    return fullPath
        .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
        + Path.DirectorySeparatorChar;
}
Run Code Online (Sandbox Code Playgroud)

或作为扩展方法:

public static string GetFullPathWithEndingSlashes(this string input)
{
    return Path.GetFullPath(input)
        .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
        + Path.DirectorySeparatorChar;
}
Run Code Online (Sandbox Code Playgroud)