【问题标题】:How to match two paths pointing to the same file?如何匹配指向同一个文件的两个路径?
【发布时间】:2012-07-12 23:48:02
【问题描述】:

我有两个包含音乐文件目录路径的列表,我想确定哪些文件存储在两个列表中,哪些只存储在一个列表中。问题在于两个列表的路径格式不同。

格式示例:

List1: 文件://localhost//FILE/Musik/30%20Seconds%20To%20Mars.mp3
List2: \\FILE\Musik\30 Seconds To Mars.mp3

如何比较这两个文件路径并将它们匹配到同一个源?

【问题讨论】:

  • 试试 FileInfo.FullPath,但我不确定它能否解决歧义...
  • @SwanandPurankar:据我了解,这个问题是关于检测相等的文件路径,而不是内容。
  • 您确定这些示例路径是真实的吗?特别是“列表 2”意味着您在名为“FILE”的计算机上拥有共享“Musik”,而该计算机恰好是本地计算机。虽然在技术上是有效的,但它看起来很奇怪。 List2 作为 "\\localhost\FILE\Musik\..." 会更有意义。
  • @Christian.K:我很确定。所有文件都位于我可以通过这两种路径格式访问的外部服务器上。
  • 如果它们在外部服务器上,那么 file://servername/FILE/Musik/...\\servername\Musik\...\\servername\FILE\Musik\... 会更明智,当然是 YMMV :-)

标签: c# path filesystems


【解决方案1】:

我认为最好的方法是将其中一个路径临时转换为另一个路径的格式。我建议您更改第一个以匹配第二个。

string List1 = "file://localhost//FILE/Musik/30%20Seconds%20To%20Mars.mp3" 
string List2 = "\\FILE\Musik\30 Seconds To Mars.mp3"

我建议你使用 Replace() 方法。

  1. 去掉“file://localhost”:

    var tempStr = List1.Replace("file://localhost", "");
    
  2. 将所有 '%20' 改为空格:

    tempStr = List1.Replace("%20", " ");
    
  3. 把所有的'/'改成'\':

    tempStr = List1.Replace("/", "\");
    

瞧!到匹配格式的字符串!

【讨论】:

  • 这只会比较字符串,而不是路径。你怎么知道你可以摆脱file://localhost?这样做意味着\\FILE\Musik 共享实际上在本地计算机上。
  • 我认为你应该看看你是如何创建列表并制定一个可靠的一致方法。在我看来,\\FILE 是否在名为 FILE 的服务器上?或者至少根据 UNC 路径格式。
  • 直接操作字符串当然是一种可行的选择,但我希望有一种更简单、更干净的方法。
  • @PhilCartmell:是的,\\FILE 是一个服务器。 List1 基本上是使用 localhost 格式的 iTunes library.xml 文件的副本。 List2 中的格式是我通过 Directory.EnumerateFiles() 映射目录时指定的默认格式,所以我想可以用 List2 做一些不同的事情。
  • 嗨 - 你测试我的代码了吗?只是想知道它是否有效/有帮助?
【解决方案2】:

使用python:你可以像这样轻松比较两个文件

    >>> import filecmp
    >>> filecmp.cmp('file1.txt', 'file1.txt')
    True
    >>> filecmp.cmp('file1.txt', 'file2.txt')
    False

要使用 file:// 语法打开文件,请使用 URLLIB

    >>> import urllib
    >>> file1 = urllib.urlopen('file://localhost/tmp/test')

对于普通文件路径使用标准文件打开。

    >>> file2 = open('/pathtofile','r')

【讨论】:

    【解决方案3】:

    答案取决于您对“同一文件”的概念。如果您只想检查文件是否相等,但不是同一个文件,您可以简单地生成文件内容的哈希并进行比较。如果哈希值相等(请使用强哈希值,例如 SHA-256),您可以确信文件也是。同样,您当然也可以逐字节比较文件。

    如果您真的想确定这两个文件实际上是同一个文件,即只是通过不同的方式(如文件 URL 或 UNC 路径)寻址,那么您还有一些工作要做。

    首先,您需要找出每个地址的真实文件系统路径。例如,您需要找到 UNC 路径和/或文件 URL(通常是 URL 本身)后面的文件系统路径。对于远程计算机上共享的 UNC 路径,您甚至可以这样做。

    此外,即使您以某种方式找到了本地路径,您也需要处理本地路径的不同重定向机制(在 Windows 联结点/重解析点/链接上;在 UNIX 符号或硬链接上)。例如,您可以使用文件系统链接作为源进行共享,而文件 URL 使用真实的源路径。所以对于不经意的观察者来说,它们仍然看起来像不同的文件。

    说了这么多,“算法”应该是这样的:

    • 找出您拥有的 URL、UNC 路径/共享等的源路径
    • 从这些路径中找出本地源路径(考虑链接/交汇点、subst.exe 等)
    • 如有必要,规范化这些路径(即 a/b/../c 实际上是 a/c
    • 比较生成的路径。

    【讨论】:

      【解决方案4】:

      我完全同意 Christian,你应该重新考虑列表的结构,但下面的内容应该能让你继续前进。

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      
      namespace ConsoleApplication5
      {
          class Program
          {
              public static List<string> SanitiseList(List<string> list)
              {
      
                  List<string> sanitisedList = new List<string>();
      
                  foreach (string filename in list)
                  {
                      String sanitisedFilename = String.Empty;
      
                      if (!String.IsNullOrEmpty(filename))
                      {
                          sanitisedFilename = filename;
      
                          // get rid of the encoding
                          sanitisedFilename = Uri.UnescapeDataString(sanitisedFilename);
      
                          // first of all change all back-slahses to forward slashes
                          sanitisedFilename = sanitisedFilename.Replace(@"\", @"/");
      
                          // if we have two back-slashes at the beginning assume its localhsot
                          if (sanitisedFilename.Substring(0, 2) == "//")
                          {
                              // remove these first double slashes and stick in localhost
      
                              sanitisedFilename = sanitisedFilename.TrimStart('/');
                              sanitisedFilename = sanitisedFilename = "//localhost" + "/" + sanitisedFilename;
                          }
      
                          // remove file
                          sanitisedFilename = sanitisedFilename.Replace(@"file://", "//");
      
                          // remove double back-slashes
                          sanitisedFilename = sanitisedFilename.Replace("\\", @"\");
      
                          // remove double forward-slashes (but not the first two)
                          sanitisedFilename = sanitisedFilename.Substring(0,2) + sanitisedFilename.Substring(2, sanitisedFilename.Length - 2).Replace("//", @"/");
      
                      }
      
                      if (!String.IsNullOrEmpty(sanitisedFilename))
                      {
                          sanitisedList.Add(sanitisedFilename);
                      }
                  }
      
                  return sanitisedList;
              }
      
              static void Main(string[] args)
              {
      
                  List<string> listA = new List<string>();
                  List<string> listB = new List<string>();
      
                  listA.Add("file://localhost//FILE/Musik/BritneySpears.mp3");
                  listA.Add("file://localhost//FILE/Musik/30%20Seconds%20To%20Mars.mp3");
                  listB.Add("file://localhost//FILE/Musik/120%20Seconds%20To%20Mars.mp3");
      
                  listB.Add(@"\\FILE\Musik\30 Seconds To Mars.mp3");
                  listB.Add(@"\\FILE\Musik\5 Seconds To Mars.mp3");
      
                  listA = SanitiseList(listA);
                  listB = SanitiseList(listB);
      
                  List<string> missingFromA = listB.Except(listA).ToList();
                  List<string> missingFromB = listA.Except(listB).ToList();
      
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-13
        • 2013-03-17
        • 2021-08-06
        • 2015-07-01
        • 2016-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多