Определите, указывают ли два имени каталога на один и тот же каталог - PullRequest
2 голосов
/ 24 марта 2011

У меня есть две строки, содержащие пути к папкам. Есть ли способ определить, указывают ли они на одно и то же место? Сравнение строк кажется немного ненадежным, учитывая такие вещи, как нечувствительность к регистру, 8.3 искажение длины имени файла, замена и т. Д.

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

String1 = "c:\Program Files\MyFolder\"
String2 = "C:\PROGRA~1\MYFOLDER"

Ответы [ 3 ]

6 голосов
/ 24 марта 2011

Следующий код должен работать для файлов (включая жесткие ссылки) и каталогов (включая соединения), но оба пути должны быть действительными!

#include <windows.h>
#include <stdio.h>

BOOL ArePathsEqual(LPCTSTR path1,LPCTSTR path2) 
{
    BY_HANDLE_FILE_INFORMATION bhfi1,bhfi2;
    HANDLE h1, h2 = NULL;
    DWORD access = 0;
    DWORD share = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;

    h1 = CreateFile(path1,access,share,NULL,OPEN_EXISTING,(GetFileAttributes(path1)&FILE_ATTRIBUTE_DIRECTORY)?FILE_FLAG_BACKUP_SEMANTICS:0,NULL);
    if (INVALID_HANDLE_VALUE != h1) 
    {
        if (!GetFileInformationByHandle(h1,&bhfi1)) bhfi1.dwVolumeSerialNumber = 0;
        h2 = CreateFile(path2,access,share,NULL,OPEN_EXISTING,(GetFileAttributes(path2)&FILE_ATTRIBUTE_DIRECTORY)?FILE_FLAG_BACKUP_SEMANTICS:0,NULL);
        if (!GetFileInformationByHandle(h2,&bhfi2)) bhfi2.dwVolumeSerialNumber = bhfi1.dwVolumeSerialNumber + 1;
    }
    CloseHandle(h1);
    CloseHandle(h2);
    return INVALID_HANDLE_VALUE != h1 && INVALID_HANDLE_VALUE != h2 
    && bhfi1.dwVolumeSerialNumber==bhfi2.dwVolumeSerialNumber
    && bhfi1.nFileIndexHigh==bhfi2.nFileIndexHigh
    && bhfi1.nFileIndexLow==bhfi2.nFileIndexLow ;
}

void main() 
{
    BOOL bRet = ArePathsEqual("c:\\program files","c:\\progra~1");
    printf("ArePathsEqual: %d\n",bRet);
}
2 голосов
/ 24 марта 2011

Для лучшей производительности вы должны сократить пути до канонической формы. Это 8.3 (GetShortPathName) и строчные буквы.

1 голос
/ 24 марта 2011

Это образец C #.Если вы используете какой-то другой язык, то идея та же.Используйте GetLongPathName и / или GetShortPathName из kernel32.dll и сравните их:

 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
 public static extern int GetLongPathName(
    [MarshalAs(UnmanagedType.LPTStr)]
    string path,
    [MarshalAs(UnmanagedType.LPTStr)]
    StringBuilder longPath,
    int longPathLength
    );

 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
 public static extern int GetShortPathName(
    [MarshalAs(UnmanagedType.LPTStr)]
    string path,
    [MarshalAs(UnmanagedType.LPTStr)]
    StringBuilder shortPath,
    int shortPathLength
    );


function bool PathsAreEqual(string path1, string path2)
{
    StringBuilder shortPath1 = new StringBuilder(255);
    StringBuilder shortPath2 = new StringBuilder(255);
    GetShortPathName(path1, shortPath1, shortPath1.Capacity);
    GetShortPathName(path2, shortPath2, shortPath2.Capacity);

    return shortPath1.ToString().ToLower() == shortPath2.ToString().ToLower();

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...