【问题标题】:Does FileInfo.Extension return the last *.* pattern, or something else?FileInfo.Extension 是否返回最后一个 *.* 模式或其他内容?
【发布时间】:2012-10-02 17:47:55
【问题描述】:

我很好奇以下行为到底是什么:

FileInfo info = new FileInfo("C:/testfile.txt.gz");
string ext = info.Extension;

这会返回“.txt.gz”还是“.gz”?

如果有更多扩展名,例如“.txt.gz.zip”或类似的东西,会有什么行为?

编辑:

需要说明的是,我已经对此进行了测试。我想要一个属性的解释。

【问题讨论】:

  • 您是否运行了代码以查看它返回的内容?真的很容易做到这一点,因为您已经编写了代码。
  • 当然,我只想了解 info.Extension 究竟做了什么,所以我可以围绕这些假设编写单元测试 :)
  • 对于那些投反对票的人 - 我问这个不是因为我懒得写自己的测试,我问是因为我想知道幕后发生了什么。
  • 我听到了。如果您以前没有使用过它,ILSpy 是一个很好的工具,可以检查各种 .Net 方法的作用。 If 有时可能会很慢,但它非常适合查看框架的各个部分是如何编写的。
  • @Gromer 我同意...还可以让您深入了解模式和实践 - 无论您在做什么,这都是一个很好的工具。

标签: c# string file-extension fileinfo


【解决方案1】:

它将返回 .gz,但 MSDN (FileSystemInfo.Extension Property) 的解释不清楚原因:

"Extension 属性返回 FileSystemInfo 扩展名,包括句点 (.)。例如,对于文件 c:\NewFile.txt,此属性返回“.txt”。"

所以我用反射器查找了Extension属性的代码:

public string Extension
{
    get
    {
        int length = this.FullPath.Length;
        int startIndex = length;
        while (--startIndex >= 0)
        {
            char ch = this.FullPath[startIndex];
            if (ch == '.')
            {
                return this.FullPath.Substring(startIndex, length - startIndex);
            }
            if (((ch == Path.DirectorySeparatorChar) || (ch == Path.AltDirectorySeparatorChar)) || (ch == Path.VolumeSeparatorChar))
            {
                break;
            }
        }
        return string.Empty;
    }
}

它会检查文件路径末尾的每个字符,直到找到一个点,然后从点返回一个子字符串到文件路径的末尾。

【讨论】:

  • 太好了,这正是我要找的,谢谢!
  • 这是一个实现细节,而不是你应该依赖的东西。您应该依赖的是文档。实施细节可能会发生变化。
  • @hvd 文档不清楚这种情况下的行为。来自MSDNThe Extension property returns the FileSystemInfo extension, including the period (.). For example, for a file c:\NewFile.txt, this property returns ".txt".
  • 对我来说似乎非常清楚。它返回“扩展名”。什么不清楚?我不明白这种混淆。
  • 扩展名可能是“多点的”,如 SaveFileDialog。
【解决方案2】:
[TestCase(@"C:/testfile.txt.gz", ".gz")]
[TestCase(@"C:/testfile.txt.gz.zip", ".zip")]
[TestCase(@"C:/testfile.txt.gz.SO.jpg", ".jpg")]
public void TestName(string fileName, string expected)
{
    FileInfo info = new FileInfo(fileName);
    string actual = info.Extension;
    Assert.AreEqual(actual, expected);
}

全部通过

【讨论】:

    【解决方案3】:

    它从最后一个点返回扩展名,因为它无法猜测文件名的另一部分是否是扩展名的一部分。对于testfile.txt.gz,您可以争辩说扩展名是.txt.gz,但System.Data.dll 呢?扩展名应该是.Data.dll 吗?可能不会……没有办法猜测,所以Extension 属性不会尝试。

    【讨论】:

    • Windows 是否指定任何扩展名可以包含句点的位置?我从来没有见过,所以我认为扩展是最后一个时期之后的任何东西。
    【解决方案4】:

    文件扩展名从最后一个点开始。不幸的是,FileSystemInfo.Extension 的文档没有回答这个问题,但它在逻辑上必须返回与 Path.GetExtension 相同的值,文档指出:

    备注

    path 的扩展是通过在 path 中搜索句点 (.) 获得的,从 path 中的最后一个字符开始,一直到 path 的开头。如果在 DirectorySeparatorChar 或 AltDirectorySeparatorChar 字符之前找到句点,则返回的字符串包含句点及其后面的字符;否则,返回 Empty。

    有关常见 I/O 任务的列表,请参阅常见 I/O 任务。

    最好有一个关于文件名的权威答案,但我很难找到它。

    【讨论】:

    • “但它在逻辑上必须返回相同的值” - 除非你查看了 Path.GetExtension() 的代码,否则你怎么能说那?如果你有,你应该把它添加到你的帖子中。事实上,这只是你的一个假设,你知道他们对假设的看法......
    • @cogumel0 我专门发布了这个答案,因为我不想想看代码。已经有一个查看代码的答案。如果结果证明代码错误或不理想,未来的 .NET Framework 更新可能会更改代码。如果文档中有关于什么是文件扩展名和不是文件扩展名的明确承诺,那么改变的可能性就会小得多。我的回答中的评论是我能找到的最接近的。
    • 我不介意您的评论,也不介意您没有发布代码这一事实,事实上我喜欢您从 MSDN 中获取并进行了相当彻底的解释。然而,我上面强调的那句话承诺了一个无可辩驳的真理,但是因为你没有做任何事情来证明这个真理,我不得不质疑它。是什么让您毫无疑问地说FileSystemInfo.Extension 必须 返回与Path.GetExtension 相同的值?我在 MSDN 上找不到任何证据来证明是这样的,如果你没有证据证明这一点,不幸的是你只是假设两者的行为相同。
    • 事实上,即使您查看了代码并意识到它们共享相同的代码,甚至Path.GetExtension 只是在后端调用FileSystemInfo.Extension...就像你说的那样可以在任何给定时刻通知进行更改,因此在文档中没有任何内容可以表明,除非另行通知,否则就是这种情况,我认为您无法发表如此强烈的声明。简而言之,我喜欢你的回答,只是在“逻辑上必须”部分冒犯,我认为“应该”必须更适合那里。
    • @cogumel0 哦,现在我知道您是如何阅读我的答案的了。这不是我要说的。通过“逻辑上必须”,我的意思是如果Path.GetExtensionFileSystemInfo.Extension 使用不同的“扩展”定义是不合逻辑的。为了使这些方法合乎逻辑,它们必须就定义达成一致。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-21
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多