Как правильно сравнить два имени файла, чтобы убедиться, что это один и тот же файл?

Возможный дубликат:
Лучший способ определить, ссылаются ли два пути на один и тот же файл в C #

Итак, у меня есть два имени файла Windows, которые мне нужно сравнить, чтобы определить, совпадают ли они. Один мне дал пользователь, другой - другой программой. Итак, как следует сравнивать:

C:\Program Files\Application1\APP.EXE
C:\Progra~1\Applic~1\APP.EXE
C:\program files\applic~1\app.exe

Кажется, я не могу найти способ последовательно «нормализовать» путь, я пробовал использовать Path.GetFullPath (путь) и новый FileInfo (путь) .FullName, и, похоже, ни один из них не решает эту проблему.

ОБНОВИТЬ:

Path.GetFullPath (path) исправит преобразование коротких имен в длинные, но не нормализует регистр. Таким образом, требуется StringComparer.OrdinalIgnoreCase.Equals (path1, path2).


person csharptest.net    schedule 17.11.2009    source источник


Ответы (3)


Вам понадобится Path.GetFullPath() + сравнение строк без учета регистра.

Выполняем следующий код:

using System;
using System.IO;

class Test {
 static void Main ()
 {
  //string [] str = new string[] {@"c:\program files\vim\vim72", @"c:\progra~1\vim\vim72"};
  string [] str = new string[] {@"c:\program files\Refere~1\microsoft", @"c:\progra~1\Refere~1\microsoft"};
  foreach (string s in str) {
   // Call s = Environment.ExpandEnvironmentVariables (s) if needed.
   Console.WriteLine (Path.GetFullPath (s));
  }
 }
}

дает:

c:\program files\Reference Assemblies\microsoft
c:\Program Files\Reference Assemblies\microsoft
person Gonzalo    schedule 17.11.2009
comment
Удалите это быстро, прежде чем вас забьют на голосование против ... - person Philip Wallace; 17.11.2009
comment
У меня это работает. Я пробовал c: \ Progra ~ 1 \ Refere ~ 1 \ Microsoft и c: \ Program Files \ Referenced Assemblies \ microsoft ... - person Gonzalo; 17.11.2009
comment
Видимо пробовал. Я опубликовал то же самое и сразу получил 3 голоса против. - person Philip Wallace; 17.11.2009
comment
Я на всякий случай добавил свой тест и его результат в ответ. Спасибо. - person Gonzalo; 17.11.2009
comment
@xaero Вы написали, что в основном попробуйте GetFullPath, когда в вопросе говорится, что я пробовал GetFullPath. Гонсало включил необходимое сравнение без учета регистра, что, вероятно, почему оно не сработало для OP, и пример кода. - person Tim Sylvester; 17.11.2009
comment
Стоит отметить, что Path.GetFullPath не расширяет переменные, поэтому, например, сравнение %PROGRAMFILES%\Reference Assemblies\Microsoft с c:\program files\Reference Assemblies\Microsoft не будет работать. - person Tim Sylvester; 17.11.2009
comment
Легко исправить. К ответу добавлю примечание ... - person Gonzalo; 17.11.2009
comment
@ Тим - достаточно честно. В любом случае все нормально, у меня есть бейджик за удаление поста ...;) - person Philip Wallace; 17.11.2009
comment
Кроме того, я не пробовал, но GetFullPath, вероятно, не обрабатывает соединения или ссылки, поддерживаемые последними версиями NTFS. Вероятно, это не проблема для 99,9% людей. - person Tim Sylvester; 17.11.2009
comment
Да, я думал о соединениях и символических ссылках в unix, но не думал, что об этом стоит упоминать. - person Gonzalo; 17.11.2009
comment
Я использую их довольно часто, но это определенно нечасто, вам в основном приходится использовать программное обеспечение, отличное от MS, чтобы делать это вне командной строки, например: schinagl.priv.at/nt/hardlinkshellext/hardlinkshellext.html. - person Tim Sylvester; 17.11.2009
comment
GetFullPath вызывает метод монстра: paste-it.net/public/haa0ee9 - person Philip Wallace; 17.11.2009
comment
@Tim: в unix это будет readlink () и является частью системной библиотеки C. - person Gonzalo; 17.11.2009
comment
Это работает для моего ограниченного случая ... Ответы, связанные с GetFileInformationByHandle, слишком сложны, чтобы иметь с ними дело. Спасибо. - person csharptest.net; 17.11.2009

короткий тестовый прогон говорит, что приведенный ниже код будет работать для указанных путей:

bool CompareFileName(string file1, string file2)
        {
            var directory1 = Path.GetDirectoryName(file1);
            var directory2 = Path.GetDirectoryName(file2);
            var fileName1 = Path.GetFileName(file1);
            var fileName2 = Path.GetFileName(file2);

            return directory1.Equals(directory2, StringComparison.InvariantCultureIgnoreCase) &&
                   fileName1.Equals(fileName2, StringComparison.InvariantCultureIgnoreCase);
        }

это предполагает платформу Windows (предположение, сделанное из-за ориентированных на окна путей, указанных в качестве примеров путей)

person Rune FS    schedule 17.11.2009

Я использую объект FileInfo. Если вы создаете объект fileinfo для файла, который действительно существует, свойство Directory дает хорошо отформатированное имя пути.

Вы также получаете дополнительное преимущество, заключающееся в возможности проверить, существует ли файл на самом деле.

person JayG    schedule 17.11.2009