欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#實現(xiàn)快速查詢文件的方法

 更新時間:2022年06月20日 11:56:15   作者:天方  
這篇文章介紹了C#實現(xiàn)快速查詢文件的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

相信使用過Everything的人都對其超快的搜索速度印象非常深刻,它的主要原理是通過掃描NTFS磁盤的USN Journal讀取的文件列表,而不是磁盤目錄,由于USN Journal非常小,因此能實現(xiàn)快速搜索。

由于.Net程序的Dll基本上是通用的,在C#中也可以直接使用它。

    public class MFTScanner
    {
        private static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
        private const uint GENERIC_READ = 0x80000000;
        private const int FILE_SHARE_READ = 0x1;
        private const int FILE_SHARE_WRITE = 0x2;
        private const int OPEN_EXISTING = 3;
        private const int FILE_READ_ATTRIBUTES = 0x80;
        private const int FILE_NAME_IINFORMATION = 9;
        private const int FILE_FLAG_BACKUP_SEMANTICS = 0x2000000;
        private const int FILE_OPEN_FOR_BACKUP_INTENT = 0x4000;
        private const int FILE_OPEN_BY_FILE_ID = 0x2000;
        private const int FILE_OPEN = 0x1;
        private const int OBJ_CASE_INSENSITIVE = 0x40;
        private const int FSCTL_ENUM_USN_DATA = 0x900b3;

        [StructLayout(LayoutKind.Sequential)]
        private struct MFT_ENUM_DATA
        {
            public long StartFileReferenceNumber;
            public long LowUsn;
            public long HighUsn;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct USN_RECORD
        {
            public int RecordLength;
            public short MajorVersion;
            public short MinorVersion;
            public long FileReferenceNumber;
            public long ParentFileReferenceNumber;
            public long Usn;
            public long TimeStamp;
            public int Reason;
            public int SourceInfo;
            public int SecurityId;
            public FileAttributes FileAttributes;
            public short FileNameLength;
            public short FileNameOffset;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct IO_STATUS_BLOCK
        {
            public int Status;
            public int Information;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct UNICODE_STRING
        {
            public short Length;
            public short MaximumLength;
            public IntPtr Buffer;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct OBJECT_ATTRIBUTES
        {
            public int Length;
            public IntPtr RootDirectory;
            public IntPtr ObjectName;
            public int Attributes;
            public int SecurityDescriptor;
            public int SecurityQualityOfService;
        }

        //// MFT_ENUM_DATA
        [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
        private static extern bool DeviceIoControl(IntPtr hDevice, int dwIoControlCode, ref MFT_ENUM_DATA lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, int nOutBufferSize, ref int lpBytesReturned, IntPtr lpOverlapped);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);

        [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
        private static extern Int32 CloseHandle(IntPtr lpObject);

        [DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
        private static extern int NtCreateFile(ref IntPtr FileHandle, int DesiredAccess, ref OBJECT_ATTRIBUTES ObjectAttributes, ref IO_STATUS_BLOCK IoStatusBlock, int AllocationSize, int FileAttribs, int SharedAccess, int CreationDisposition, int CreateOptions, int EaBuffer,
        int EaLength);

        [DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
        private static extern int NtQueryInformationFile(IntPtr FileHandle, ref IO_STATUS_BLOCK IoStatusBlock, IntPtr FileInformation, int Length, int FileInformationClass);

        private IntPtr m_hCJ;
        private IntPtr m_Buffer;
        private int m_BufferSize;

        private string m_DriveLetter;

        private class FSNode
        {
            public long FRN;
            public long ParentFRN;
            public string FileName;

            public bool IsFile;
            public FSNode(long lFRN, long lParentFSN, string sFileName, bool bIsFile)
            {
                FRN = lFRN;
                ParentFRN = lParentFSN;
                FileName = sFileName;
                IsFile = bIsFile;
            }
        }

        private IntPtr OpenVolume(string szDriveLetter)
        {

            IntPtr hCJ = default(IntPtr);
            //// volume handle

            m_DriveLetter = szDriveLetter;
            hCJ = CreateFile(@"\\.\" + szDriveLetter, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);

            return hCJ;

        }


        private void Cleanup()
        {
            if (m_hCJ != IntPtr.Zero)
            {
                // Close the volume handle.
                CloseHandle(m_hCJ);
                m_hCJ = INVALID_HANDLE_VALUE;
            }

            if (m_Buffer != IntPtr.Zero)
            {
                // Free the allocated memory
                Marshal.FreeHGlobal(m_Buffer);
                m_Buffer = IntPtr.Zero;
            }

        }


        public IEnumerable<String> EnumerateFiles(string szDriveLetter)
        {
            try
            {
                var usnRecord = default(USN_RECORD);
                var mft = default(MFT_ENUM_DATA);
                var dwRetBytes = 0;
                var cb = 0;
                var dicFRNLookup = new Dictionary<long, FSNode>();
                var bIsFile = false;

                // This shouldn't be called more than once.
                if (m_Buffer.ToInt32() != 0)
                {
                    throw new Exception("invalid buffer");
                }

                // Assign buffer size
                m_BufferSize = 65536;
                //64KB

                // Allocate a buffer to use for reading records.
                m_Buffer = Marshal.AllocHGlobal(m_BufferSize);

                // correct path
                szDriveLetter = szDriveLetter.TrimEnd('\\');

                // Open the volume handle
                m_hCJ = OpenVolume(szDriveLetter);

                // Check if the volume handle is valid.
                if (m_hCJ == INVALID_HANDLE_VALUE)
                {
                    string errorMsg = "Couldn't open handle to the volume.";
                    if (!IsAdministrator())
                        errorMsg += "Current user is not administrator";

                    throw new Exception(errorMsg);
                }

                mft.StartFileReferenceNumber = 0;
                mft.LowUsn = 0;
                mft.HighUsn = long.MaxValue;

                do
                {
                    if (DeviceIoControl(m_hCJ, FSCTL_ENUM_USN_DATA, ref mft, Marshal.SizeOf(mft), m_Buffer, m_BufferSize, ref dwRetBytes, IntPtr.Zero))
                    {
                        cb = dwRetBytes;
                        // Pointer to the first record
                        IntPtr pUsnRecord = new IntPtr(m_Buffer.ToInt32() + 8);

                        while ((dwRetBytes > 8))
                        {
                            // Copy pointer to USN_RECORD structure.
                            usnRecord = (USN_RECORD)Marshal.PtrToStructure(pUsnRecord, usnRecord.GetType());

                            // The filename within the USN_RECORD.
                            string FileName = Marshal.PtrToStringUni(new IntPtr(pUsnRecord.ToInt32() + usnRecord.FileNameOffset), usnRecord.FileNameLength / 2);

                            bIsFile = !usnRecord.FileAttributes.HasFlag(FileAttributes.Directory);
                            dicFRNLookup.Add(usnRecord.FileReferenceNumber, new FSNode(usnRecord.FileReferenceNumber, usnRecord.ParentFileReferenceNumber, FileName, bIsFile));

                            // Pointer to the next record in the buffer.
                            pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usnRecord.RecordLength);

                            dwRetBytes -= usnRecord.RecordLength;
                        }

                        // The first 8 bytes is always the start of the next USN.
                        mft.StartFileReferenceNumber = Marshal.ReadInt64(m_Buffer, 0);


                    }
                    else
                    {
                        break; // TODO: might not be correct. Was : Exit Do

                    }

                } while (!(cb <= 8));

                // Resolve all paths for Files
                foreach (FSNode oFSNode in dicFRNLookup.Values.Where(o => o.IsFile))
                {
                    string sFullPath = oFSNode.FileName;
                    FSNode oParentFSNode = oFSNode;

                    while (dicFRNLookup.TryGetValue(oParentFSNode.ParentFRN, out oParentFSNode))
                    {
                        sFullPath = string.Concat(oParentFSNode.FileName, @"\", sFullPath);
                    }
                    sFullPath = string.Concat(szDriveLetter, @"\", sFullPath);

                    yield return sFullPath;
                }
            }
            finally
            {
                //// cleanup
                Cleanup();
            }
        }

        public static bool IsAdministrator()
        {
            WindowsIdentity identity = WindowsIdentity.GetCurrent();
            WindowsPrincipal principal = new WindowsPrincipal(identity);
            return principal.IsInRole(WindowsBuiltInRole.Administrator);
        }
    }

本文還提供了一個擴展方法,方便我們獲取某個磁盤下的所有的文件名。 

    public static class DriveInfoExtension
    {
        public static IEnumerable<String> EnumerateFiles(this DriveInfo drive)
        {
            return (new MFTScanner()).EnumerateFiles(drive.Name);
        }
    }

需要注意的是,讀取USN Journal是需要管理員權(quán)限的,因此使用這個類需要管理員權(quán)限才能正常運行。

另外,這個類封裝的也略為簡單,只讀取了文件名,實際上還可以讀取文件大小,屬性等常用信息,修改一下代碼非常容易獲取這些屬性。通過它們可以非常方便寫出一些分析磁盤空間占用的程序,這里就不舉例了。

到此這篇關(guān)于C#實現(xiàn)快速查詢文件的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#中寫入和讀取TXT文件問題

    C#中寫入和讀取TXT文件問題

    這篇文章主要介紹了C#中寫入和讀取TXT文件問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • C#操作Access通用類實例

    C#操作Access通用類實例

    這篇文章主要介紹了C#操作Access通用類,實例分析了C#操作access的各種常見技巧,非常具有實用價值,需要的朋友可以參考下
    2015-06-06
  • C#圖像處理之邊緣檢測(Sobel)的方法

    C#圖像處理之邊緣檢測(Sobel)的方法

    這篇文章主要介紹了C#圖像處理之邊緣檢測(Sobel)的方法,使用自定義sobel算子函數(shù)實現(xiàn)對圖像邊緣的檢測功能,需要的朋友可以參考下
    2015-04-04
  • C#讀取命令行參數(shù)的方法

    C#讀取命令行參數(shù)的方法

    這篇文章主要介紹了C#讀取命令行參數(shù)的方法,可實現(xiàn)讀取程序輸入命令行的所有參數(shù),便于調(diào)試程序,比較簡單實用,需要的朋友可以參考下
    2015-04-04
  • C#中String.LastIndexOf方法小結(jié)

    C#中String.LastIndexOf方法小結(jié)

    String.LastIndexOf()是C#中string類的一個方法,它用于在字符串中查找指定子字符串(或字符)最后一次出現(xiàn)的位置,并返回其索引,本文主要介紹了C#中String.LastIndexOf方法小結(jié),感興趣的可以了解一下
    2024-01-01
  • C#實現(xiàn)的簡單隨機數(shù)產(chǎn)生器功能示例

    C#實現(xiàn)的簡單隨機數(shù)產(chǎn)生器功能示例

    這篇文章主要介紹了C#實現(xiàn)的簡單隨機數(shù)產(chǎn)生器功能,涉及C#簡單界面布局、事件響應(yīng)及隨機數(shù)生成相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09
  • C#實現(xiàn)MQTT服務(wù)端與客戶端通訊功能

    C#實現(xiàn)MQTT服務(wù)端與客戶端通訊功能

    這篇文章介紹了C#實現(xiàn)MQTT服務(wù)端與客戶端通訊的功能,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • C#實現(xiàn)在啟動目錄創(chuàng)建快捷方式的方法

    C#實現(xiàn)在啟動目錄創(chuàng)建快捷方式的方法

    這篇文章主要介紹了C#實現(xiàn)在啟動目錄創(chuàng)建快捷方式的方法,涉及C#快捷方式的創(chuàng)建技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09
  • C# ping網(wǎng)絡(luò)IP 實現(xiàn)網(wǎng)絡(luò)狀態(tài)檢測的方法

    C# ping網(wǎng)絡(luò)IP 實現(xiàn)網(wǎng)絡(luò)狀態(tài)檢測的方法

    下面小編就為大家?guī)硪黄狢# ping網(wǎng)絡(luò)IP 實現(xiàn)網(wǎng)絡(luò)狀態(tài)檢測的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • 詳解C#如何自定義書寫中間件

    詳解C#如何自定義書寫中間件

    中間件是一種裝配到應(yīng)用管道以處理請求和響應(yīng)的軟件,是介于request與response處理過程之間的一個插件,本文主要介紹了如何自定義書寫中間件,需要的可以參考下
    2023-08-08

最新評論