c#获取文件或文件夹id
文件(夹)比较受诸多因素可能出现错漏,比如大小写,分隔符,还有父路径,短路径等影响,单纯的通过字符串比较出错概率很大,本文但要的方法是获取文件或文件夹的id,再来比较id判断提供的路径是否指向同一对象,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Win32.SafeHandles; using System.IO; using System.Runtime.InteropServices; using System.ComponentModel; namespace Demo { class Program { const uint FSCTL_GET_OBJECT_ID = 0x0009009c; internal const int GENERIC_READ = unchecked((int)0x80000000), FILE_FLAG_BACKUP_SEMANTICS = unchecked((int)0x02000000), OPEN_EXISTING = unchecked((int)3); [StructLayout(LayoutKind.Sequential)] public struct FILE_OBJECTID_BUFFER { public struct Union { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] BirthVolumeId; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] BirthObjectId; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] DomainId; } [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] ObjectId; public Union BirthInfo; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)] public byte[] ExtendedInfo; } [StructLayout(LayoutKind.Sequential)] 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; } [DllImport("kernel32.dll", SetLastError = true)] public static extern bool DeviceIoControl( SafeFileHandle hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, [Out] IntPtr lpOutBuffer, int nOutBufferSize, ref uint lpBytesReturned, IntPtr lpOverlapped ); [DllImport("kernel32.dll", SetLastError = true)] public static extern SafeFileHandle CreateFile( String fileName, int dwDesiredAccess, System.IO.FileShare dwShareMode, IntPtr securityAttrs_MustBeZero, System.IO.FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile_MustBeZero ); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool GetFileInformationByHandle( IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation); public static String GetFileId(String path) { using (var fs = File.Open( path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite) ) { BY_HANDLE_FILE_INFORMATION info; GetFileInformationByHandle(fs.Handle, out info); return String.Format( "{0:x}", ((info.FileIndexHigh << 32) | info.FileIndexLow)); } } public static FILE_OBJECTID_BUFFER GetFolderIdBuffer(String path) { using (var hFile = CreateFile( path, GENERIC_READ, FileShare.Read, IntPtr.Zero, (FileMode)OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero )) { if (null == hFile || hFile.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); var buffer = default(FILE_OBJECTID_BUFFER); var nOutBufferSize = Marshal.SizeOf(buffer); var lpOutBuffer = Marshal.AllocHGlobal(nOutBufferSize); var lpBytesReturned = default(uint); var result = DeviceIoControl( hFile, FSCTL_GET_OBJECT_ID, IntPtr.Zero, 0, lpOutBuffer, nOutBufferSize, ref lpBytesReturned, IntPtr.Zero ); if (!result) throw new Win32Exception(Marshal.GetLastWin32Error()); var type = typeof(FILE_OBJECTID_BUFFER); buffer = (FILE_OBJECTID_BUFFER) Marshal.PtrToStructure(lpOutBuffer, type); Marshal.FreeHGlobal(lpOutBuffer); return buffer; } } static void Main(string[] args) { var fileid1 = GetFileId(@"C:\Users\a\Desktop\abc.png"); var fileid2 = GetFileId(@"C:\Users\a\Desktop\ABC.png"); var folderid1 = GetFolderIdBuffer(@"C:\Users\a\Desktop\").ObjectId.Reverse() .Select(x => x.ToString("x2")).Aggregate(String.Concat); var folderid2 = GetFolderIdBuffer(@"c:\users\a\..\a\desktop").ObjectId.Reverse() .Select(x => x.ToString("x2")).Aggregate(String.Concat); } } }
桂棹兮兰桨,击空明兮溯流光。