在Visual Studio的即时窗口中:
> Path.Combine(@"C:\x", "y")
"C:\\x\\y"
> Path.Combine(@"C:\x", @"\y")
"\\y"
看来它们应该是一样的。
旧的FileSystemObject.BuildPath()不是这样工作的……
在Visual Studio的即时窗口中:
> Path.Combine(@"C:\x", "y")
"C:\\x\\y"
> Path.Combine(@"C:\x", @"\y")
"\\y"
看来它们应该是一样的。
旧的FileSystemObject.BuildPath()不是这样工作的……
当前回答
这两个方法可以避免您意外地连接两个都有分隔符的字符串。
public static string Combine(string x, string y, char delimiter) {
return $"{ x.TrimEnd(delimiter) }{ delimiter }{ y.TrimStart(delimiter) }";
}
public static string Combine(string[] xs, char delimiter) {
if (xs.Length < 1) return string.Empty;
if (xs.Length == 1) return xs[0];
var x = Combine(xs[0], xs[1], delimiter);
if (xs.Length == 2) return x;
var ys = new List<string>();
ys.Add(x);
ys.AddRange(xs.Skip(2).ToList());
return Combine(ys.ToArray(), delimiter);
}
其他回答
这是一个哲学问题(也许只有微软能真正回答这个问题),因为它正在做文档中所说的事情。
System.IO.Path.Combine
如果path2包含一个绝对路径,则此方法返回path2。
下面是. net源代码中的实际Combine方法。你可以看到它调用了CombineNoChecks,然后在path2上调用ispathooot,如果是的话返回该路径:
public static String Combine(String path1, String path2) {
if (path1==null || path2==null)
throw new ArgumentNullException((path1==null) ? "path1" : "path2");
Contract.EndContractBlock();
CheckInvalidPathChars(path1);
CheckInvalidPathChars(path2);
return CombineNoChecks(path1, path2);
}
internal static string CombineNoChecks(string path1, string path2)
{
if (path2.Length == 0)
return path1;
if (path1.Length == 0)
return path2;
if (IsPathRooted(path2))
return path2;
char ch = path1[path1.Length - 1];
if (ch != DirectorySeparatorChar && ch != AltDirectorySeparatorChar &&
ch != VolumeSeparatorChar)
return path1 + DirectorySeparatorCharAsString + path2;
return path1 + path2;
}
我不知道理由是什么。我想解决方案是剥离(或修剪)DirectorySeparatorChar从第二个路径的开始;也许你可以编写自己的Combine方法,然后调用Path.Combine()。
这实际上是有意义的,在某种程度上,考虑到(相对)路径通常是如何处理的:
string GetFullPath(string path)
{
string baseDir = @"C:\Users\Foo.Bar";
return Path.Combine(baseDir, path);
}
// Get full path for RELATIVE file path
GetFullPath("file.txt"); // = C:\Users\Foo.Bar\file.txt
// Get full path for ROOTED file path
GetFullPath(@"C:\Temp\file.txt"); // = C:\Temp\file.txt
真正的问题是:为什么以“\”开头的路径被认为是“根路径”?这对我来说也很新鲜,但它在Windows上是这样工作的:
new FileInfo("\windows"); // FullName = C:\Windows, Exists = True
new FileInfo("windows"); // FullName = C:\Users\Foo.Bar\Windows, Exists = False
我想解决这个问题:
string sample1 = "configuration/config.xml";
string sample2 = "/configuration/config.xml";
string sample3 = "\\configuration/config.xml";
string dir1 = "c:\\temp";
string dir2 = "c:\\temp\\";
string dir3 = "c:\\temp/";
string path1 = PathCombine(dir1, sample1);
string path2 = PathCombine(dir1, sample2);
string path3 = PathCombine(dir1, sample3);
string path4 = PathCombine(dir2, sample1);
string path5 = PathCombine(dir2, sample2);
string path6 = PathCombine(dir2, sample3);
string path7 = PathCombine(dir3, sample1);
string path8 = PathCombine(dir3, sample2);
string path9 = PathCombine(dir3, sample3);
当然,所有路径1-9最后都应该包含一个等效的字符串。这是我想出的PathCombine方法:
private string PathCombine(string path1, string path2)
{
if (Path.IsPathRooted(path2))
{
path2 = path2.TrimStart(Path.DirectorySeparatorChar);
path2 = path2.TrimStart(Path.AltDirectorySeparatorChar);
}
return Path.Combine(path1, path2);
}
我还认为这是相当恼人的字符串处理必须手动完成,我对这背后的原因很感兴趣。
原因:
第二个URL被认为是一个绝对路径,如果最后一个路径是一个绝对路径,Combine方法只会返回最后一个路径。
解决方案:
只需从第二个路径(/SecondPath到SecondPath)中删除前导斜杠/,它就会正常工作。
如果你想在不丢失任何路径的情况下组合这两条路径,你可以使用这个:
?Path.Combine(@"C:\test", @"\test".Substring(0, 1) == @"\" ? @"\test".Substring(1, @"\test".Length - 1) : @"\test");
或者用变量:
string Path1 = @"C:\Test";
string Path2 = @"\test";
string FullPath = Path.Combine(Path1, Path2.IsRooted() ? Path2.Substring(1, Path2.Length - 1) : Path2);
这两种情况都返回“C:\test\test”。
首先,我计算Path2是否以/开头,如果为真,返回不带第一个字符的Path2。否则,返回完整的Path2。