我有一个扫描硬盘内容的Windows程序。我想显示一个有意义的进度条。有没有快速获取磁盘上文件总数的方法?这个数字不一定非精确 - 应该在10%左右的近似值。
答案 0 :(得分:0)
这可能是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;
}