【问题标题】:Is there a fast way to get the number of files on a disk?有没有一种快速获取磁盘上文件数量的方法?
【发布时间】:2017-02-22 23:49:20
【问题描述】:

我有一个扫描硬盘内容的 Windows 程序。我想在它这样做时显示一个有意义的进度条。有没有快速获取磁盘上文件总数的方法?这个数字不一定要精确——大约在 10% 左右就可以了。

【问题讨论】:

  • 您有管理员权限吗? Reading the content of the MFT 提供了一种更快的扫描磁盘内容的方法,如果您这样做了,您可以通过跟踪您已处理的 what percentage of the MFT 来实现一个进度条。
  • 不走运——这个程序需要能够在尽可能广泛的环境下运行。

标签: windows filesystems


【解决方案1】:

这对于 NTFS 卷是可能的。哈利约翰斯顿write的一种方式。也可以通过其他方式,通过迭代文件记录也足够快:

struct NTFS_RECORD_HEADER 
{
    enum {
        FILE = 'ELIF',
        INDX = 'XDNI',
        BAAD = 'DAAB',
        HOLE = 'ELOH',
        CHKD = 'DKHC'
    } Type;
    USHORT UsaOffset;
    USHORT UsaCount;
    USN Usn;
};

struct NTFS_FILE_RECORD_HEADER : public NTFS_RECORD_HEADER
{
    USHORT SequenceNumber;
    USHORT LinkCount;
    USHORT AttributesOffset;
    USHORT Flags;
    ULONG BytesInUse;
    ULONG BytesAllocated;
    ULONGLONG BaseFileRecord;
    USHORT NextAttributeNumber;

    enum{
        flgInUse = 1, flgDirectory = 2
    };
};

ULONG GetFileCount(HANDLE hVolume, PULONG FileCount)
{
    NTFS_VOLUME_DATA_BUFFER nvdb;

    ULONG cb, BytesReturned;
    if (!DeviceIoControl(hVolume, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &nvdb, sizeof(nvdb), &BytesReturned, NULL))
    {
        return GetLastError();
    }

    NTFS_FILE_RECORD_INPUT_BUFFER nfrib;

    cb = FIELD_OFFSET(NTFS_FILE_RECORD_OUTPUT_BUFFER, FileRecordBuffer[nvdb.BytesPerFileRecordSegment]);

    PNTFS_FILE_RECORD_OUTPUT_BUFFER pnfrob = (PNTFS_FILE_RECORD_OUTPUT_BUFFER)alloca(cb);

    union {
        PVOID FileRecordBuffer;
        NTFS_RECORD_HEADER* pnrh;
        NTFS_FILE_RECORD_HEADER* pnfrh;
    };

    FileRecordBuffer = pnfrob->FileRecordBuffer;

    // get maximum valid FileReferenceNumber
    ULONG a = 0, b = MAXLONG, N;
    do 
    {
        nfrib.FileReferenceNumber.QuadPart = N = (a + b) >> 1;

        DeviceIoControl(hVolume, FSCTL_GET_NTFS_FILE_RECORD, 
            &nfrib, sizeof nfrib, pnfrob, cb, &BytesReturned, 0) ? a = N + 1 : b = N;

    } while(a < b);

    if (!b)
    {
        return ERROR_GEN_FAILURE;
    }

    N = 0;
    nfrib.FileReferenceNumber.QuadPart = b - 1;

    // itterate [0, nfrib.FileReferenceNumber.QuadPart)
    do 
    {
        if (DeviceIoControl(hVolume, FSCTL_GET_NTFS_FILE_RECORD, 
            &nfrib, sizeof nfrib, pnfrob, cb, &BytesReturned, 0))
        {
            // are really file
            if (
                pnrh->Type == NTFS_RECORD_HEADER::FILE &&
                pnfrh->Flags & NTFS_FILE_RECORD_HEADER::flgInUse &&
                !pnfrh->BaseFileRecord
                )
            {
                N++;
            }
        }
        else
        {
            pnfrob->FileReferenceNumber.QuadPart = nfrib.FileReferenceNumber.QuadPart;
        }

    } while (0 <= (nfrib.FileReferenceNumber.QuadPart = pnfrob->FileReferenceNumber.QuadPart - 1));

    *FileCount = N;

    return NOERROR;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    • 2020-11-20
    • 1970-01-01
    相关资源
    最近更新 更多