【问题标题】:C# combining absolute and relative paths, Path.GetFullPath() inconsistentC#结合绝对路径和相对路径,Path.GetFullPath() 不一致
【发布时间】:2016-05-16 23:21:52
【问题描述】:

我注意到当我使用 Path.GetFullPath(Path.Combine(@"c:\folder\","\subfolder\file.txt")) 时,它会返回路径 c:\subfolder\file.txt,而不是预期的组合路径 c:\folder\subfolder\file.txt。这些方法似乎没有处理第二个组合输入上的“\”。有没有人遇到过这种情况并找到了合并路径的更好解决方案?

var test1 = Path.GetFullPath(Path.Combine(@"C:\users\dev\desktop\testfiles\", @".\test1.txt"));
var test2 = Path.GetFullPath(Path.Combine(@"C:\users\dev\desktop\testfiles\", @"\test2.txt"));//
var test3 = Path.GetFullPath(Path.Combine(@"C: \users\dev\desktop\testfiles\", @"test3.txt"));
var test4 = Path.GetFullPath(Path.Combine(@"C:\users\dev\desktop\testfiles\",@".\XXX\test4.txt"));
var test5 = Path.GetFullPath(Path.Combine(@"C:\users\dev\desktop\testfiles\", @"\XXX\test5.txt"));//
var test6 = Path.GetFullPath(Path.Combine(@"C:\users\dev\desktop\testfiles\", @"XXX\test6.txt"));
var test7 = Path.GetFullPath(Path.Combine(@"C:\users\dev\desktop\testfiles\", @"\somefile\that\doesnt\exist.txt"));//

结果

test1 is "C:\users\dev\desktop\testfiles\test1.txt"
test2 is wrong "\test2.txt"
test3 is "C: \users\dev\desktop\testfiles\test3.txt"
test4 is "C:\users\dev\desktop\testfiles\XXX\test4.txt"
test5 is wrong "c:\XXX\test5.txt"
test6 is "C:\users\dev\desktop\testfiles\XXX\test6.txt"
test7 is wrong "c:\somefile\that\doesnt\exist.txt"

基本上我正在做的是将源路径与文本文件中的单个文件路径结合起来,以便我可以将这些文件复制到目标,并且我想维护子文件夹层次结构。

例如文件列表相同但想要引用特定源文件夹版本的常见场景。

source path + individual file path
\\myserver\project\1.x + \dll\important.dll

应该以同样的方式复制到目的地

c:\myproject\ + \dll\important.dll

所以会有变量;源、目标、文件[数组或列表]

我目前的前进方式是使用 String.TRIM() 方法删除特殊字符。 \ / 在将路径与 Path.Combine、Path.GetFullPath 组合之前。但我想也许有人已经意识到类似情况的更好方法。

在目的地创建子文件夹也很痛苦,基本上我使用 String.LastIndexOf(@'\') 将文件名与文件夹名分开。这似乎也有点粗略,但更好的方法超出了我的经验。

类似的问题: Path.Combine absolute with relative path strings


感谢反馈,我现在知道 \file.txt 被视为完全限定(绝对)路径,这就是 combine 方法以这种方式工作的原因。

如果文件名不以下列之一开头,则该文件名相对于当前目录:

A UNC name of any format, which always start with two backslash characters ("\\"). For more information, see the next section.
A disk designator with a backslash, for example "C:\" or "d:\".
A single backslash, for example, "\directory" or "\file.txt". This is also referred to as an absolute path.

https://msdn.microsoft.com/en-nz/library/windows/desktop/aa365247(v=vs.85).aspx#fully_qualified_vs._relative_paths

【问题讨论】:

标签: c#


【解决方案1】:

基于MSDN Documentation,这是预期行为。

如果 path2 不包含根目录(例如,如果 path2 没有启动 带有分隔符或驱动器说明),结果是 两个路径的连接,中间有分隔符 特点。如果 path2 包含根,则返回 path2。

MSDN article 中讨论了分隔符。

那么让我们来看看你的测试用例:

var test1 = Path.GetFullPath(Path.Combine(@"C:\users\dev\desktop\testfiles\", @".\test1.txt"));
var test2 = Path.GetFullPath(Path.Combine(@"C:\users\dev\desktop\testfiles\", @"\test2.txt"));

Test1 行为正确,因为它将. 作为有效文件路径的一部分,并将其与第一个参数结合使用以生成组合路径。

Test2 的行为符合预期,因为 \ 是分隔符,因此如所述,它在没有第一个参数的情况下返回。

【讨论】:

  • 感谢您的澄清,这表明该方法按预期工作。我想这表明我不清楚绝对路径是什么。因为我不认为“\test2.txt”有资格作为绝对路径。我会更多地了解它。谢谢
【解决方案2】:

没有您喜欢在 .Net 框架中使用的功能 - 修剪路径或确保相对路径以“.\”开头您的真实选项(可能存在于某处的库)。


为什么代码的行为不像你喜欢的那样(不是“错误”,只是没有满足你的意外期望)。

Combine 需要决定左路径的哪一部分将保留,哪一部分将被替换。它使用常规文件系统约定来决定(“.”、“..”、“\”对于文件路径具有特殊含义)

路径开头的含义:

  • @"\" or"/" - 从当前设备的根目录开始 - 这涵盖了您不喜欢的大多数情况
  • @".\" - 表示来自当前目录(因此在组合和规范化后,它将完全按照您的意愿行事)
  • `@"..\"(可能有多个“上”)- 上一个文件夹- 这是您可能不同意的另一种情况。
  • 任何不是'/'@'\' 的字符 - 当前文件夹的文件名或路径

另请注意,以"/"@"\" 以外的任何内容结尾的路径被Path.Combine 视为文件路径,当与其他路径组合时,它将丢失最后一段。

【讨论】:

  • 感谢您确认 .NET 没有内置任何东西来解决这个问题。这就是我主要想弄清楚的,是否有更好的方法可用。我也想接受你的回答,但只能接受一个,谢谢你的回复。你是对的,我对 combine 方法的期望是错误的,该方法现在按设计工作我意识到 \file.txt 实际上是一个绝对路径
猜你喜欢
  • 2012-10-16
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
  • 2013-07-14
  • 2010-12-17
  • 1970-01-01
  • 2011-06-15
相关资源
最近更新 更多