Уникальный идентификатор файла в окнах

Я нахожусь на PanicSans 12 ПБ w/AA на TextMate, но любовь Inconsolata на Терминале/энергии... (обсуждающий изменение моего шрифта ТМ этому..., но размеру точки 14 ПБ):)

46
задан Ash 8 December 2009 в 11:46
поделиться

3 ответа

Если вы вызовете GetFileInformationByHandle , вы получите идентификатор файла в BY_HANDLE_FILE_INFORMATION.nFileIndexHigh / Low. Этот индекс уникален в пределах тома и остается неизменным, даже если вы переместите файл (внутри тома) или переименуете его.

Если вы можете предположить, что используется NTFS, вы также можете рассмотреть возможность использования альтернативных потоков данных для сохранить метаданные.

23
ответ дан 26 November 2019 в 20:38
поделиться

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

ApproachA () - это то, что я придумал после небольшого исследования. ApproachB () создан благодаря информации в ссылках, предоставленных Маттиасом и Рубенсом. Для конкретного файла оба подхода возвращают один и тот же индекс файла (во время моего базового тестирования).

Некоторые предостережения от MSDN:

Поддержка идентификаторов файлов - это файл зависит от системы. Идентификаторы файлов не гарантированно будет уникальным с течением времени, потому что файловые системы можно использовать повторно их. В некоторых случаях идентификатор файла для файл может изменяться со временем.

В файловой системе FAT идентификатор файла генерируется из первого кластера содержащий каталог и байт смещение в каталоге запись для файла. Некоторые продукты дефрагментации меняют это байтовое смещение. (Windows в коробке дефрагментации нет.) Таким образом, FAT идентификатор файла может со временем измениться. Переименование файл в файловой системе FAT также может изменить идентификатор файла, но только если новое имя файла длиннее старого один.

В файловой системе NTFS файл хранит тот же идентификатор файла, пока он не будет удален . Вы можете заменить один файл другим файл без изменения идентификатора файла на с помощью функции ReplaceFile. Однако идентификатор файла файл замены, а не замененный файл, сохраняется как идентификатор файла получившийся файл.

Первый комментарий, выделенный жирным шрифтом, меня беспокоит. Неясно, применимо ли это утверждение только к FAT, кажется, что оно противоречит второму тексту, выделенному жирным шрифтом. Думаю, дальнейшее тестирование - единственный способ убедиться.

[Обновление: в моем тестировании индекс / идентификатор файла изменяется, когда файл перемещается с одного внутреннего жесткого диска NTFS на другой внутренний жесткий диск NTFS.]

    public class WinAPI
    {
        [DllImport("ntdll.dll", SetLastError = true)]
        public static extern IntPtr NtQueryInformationFile(IntPtr fileHandle, ref IO_STATUS_BLOCK IoStatusBlock, IntPtr pInfoBlock, uint length, FILE_INFORMATION_CLASS fileInformation);

        public struct IO_STATUS_BLOCK
        {
            uint status;
            ulong information;
        }
        public struct _FILE_INTERNAL_INFORMATION {
          public ulong  IndexNumber;
        } 

        // Abbreviated, there are more values than shown
        public enum FILE_INFORMATION_CLASS
        {
            FileDirectoryInformation = 1,     // 1
            FileFullDirectoryInformation,     // 2
            FileBothDirectoryInformation,     // 3
            FileBasicInformation,         // 4
            FileStandardInformation,      // 5
            FileInternalInformation      // 6
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool GetFileInformationByHandle(IntPtr hFile,out BY_HANDLE_FILE_INFORMATION lpFileInformation);

        public struct BY_HANDLE_FILE_INFORMATION
        {
            public uint FileAttributes;
            public FILETIME CreationTime;
            public FILETIME LastAccessTime;
            public FILETIME LastWriteTime;
            public uint VolumeSerialNumber;
            public uint FileSizeHigh;
            public uint FileSizeLow;
            public uint NumberOfLinks;
            public uint FileIndexHigh;
            public uint FileIndexLow;
        }
  }

  public class Test
  {
       public ulong ApproachA()
       {
                WinAPI.IO_STATUS_BLOCK iostatus=new WinAPI.IO_STATUS_BLOCK();

                WinAPI._FILE_INTERNAL_INFORMATION objectIDInfo = new WinAPI._FILE_INTERNAL_INFORMATION();

                int structSize = Marshal.SizeOf(objectIDInfo);

                FileInfo fi=new FileInfo(@"C:\Temp\testfile.txt");
                FileStream fs=fi.Open(FileMode.Open,FileAccess.Read,FileShare.ReadWrite);

                IntPtr res=WinAPI.NtQueryInformationFile(fs.Handle, ref iostatus, memPtr, (uint)structSize, WinAPI.FILE_INFORMATION_CLASS.FileInternalInformation);

                objectIDInfo = (WinAPI._FILE_INTERNAL_INFORMATION)Marshal.PtrToStructure(memPtr, typeof(WinAPI._FILE_INTERNAL_INFORMATION));

                fs.Close();

                Marshal.FreeHGlobal(memPtr);   

                return objectIDInfo.IndexNumber;

       }

       public ulong ApproachB()
       {
               WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo=new WinAPI.BY_HANDLE_FILE_INFORMATION();

                FileInfo fi=new FileInfo(@"C:\Temp\testfile.txt");
                FileStream fs=fi.Open(FileMode.Open,FileAccess.Read,FileShare.ReadWrite);

                WinAPI.GetFileInformationByHandle(fs.Handle, out objectFileInfo);

                fs.Close();

                ulong fileIndex = ((ulong)objectFileInfo.FileIndexHigh << 32) + (ulong)objectFileInfo.FileIndexLow;

                return fileIndex;   
       }
  }
31
ответ дан 26 November 2019 в 20:38
поделиться
4
ответ дан 26 November 2019 в 20:38
поделиться