Определите, указывают ли два имени каталога на один и тот же каталог
У меня есть две строки, содержащие пути к папкам. Есть ли способ определить, указывают ли они каким-то образом на одно и то же место? Сравнение строк кажется немного ненадежным, учитывая такие вещи, как нечувствительность к регистру, искажение длины файла 8.3, subst и т. д.
Чтобы проиллюстрировать, как я могу определить, что эти два указывают на одно и то же место:
String1 = "c:Program FilesMyFolder"
String2 = "C:PROGRA~1MYFOLDER"
3 ответов:
Следующий код должен работать для файлов (включая жесткие ссылки) и каталогов (включая соединения), но оба пути должны быть допустимыми!
#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); }
Для достижения наилучшей производительности следует сократить пути до канонической формы. Это 8.3 (GetShortPathName) и нижний регистр.
Это образец 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(); }
Comments