Пожалуйста, прочтите, прежде чем цитировать «репост» - я знаю, что задавались похожие вопросы, но я еще не нашел удовлетворительного ответа
Моя цель - предоставить древовидную структуру каталогов использования дискового пространства, позволяющую пользователю детализировать иерархию, чтобы найти папки значительного размера.
Программа TreeSize является прекрасным примером этого, и я хочу получить такое же время отклика, что и эта программа.
Мой текущий код может перебирать мои 480 ГБ файлов примерно за 25 секунд с использованием MFT. Я ищу с этого момента, чтобы начать создание размеров каталогов, получив информацию о файле (MFT содержит только fileName и parentId, а не полный путь к файлу)
Чтобы получить информацию о файле из записи журнала MFT, мой текущий код вызывает
TCHAR filePath[MAX_PATH];
HANDLE hh = OpenFileById(hDevice, &(getFileIdDescriptor(pRecord->FileReferenceNumber)), 0, 0, 0, 0);
GetFinalPathNameByHandle(hh, filePath, MAX_PATH, 0);
К сожалению, этот код увеличивает общее время выполнения программы с 25 секунд до 5 минут.
Есть ли лучший способ получить информацию о файле?
Большое спасибо, если вы предлагаете FindFirstFile и FindNextFile, но для обработки больших каталогов эти параметры слишком медленные
Код, как показано ниже (я не программист на C, как вы могли заметить!)
#include <iostream>
#include <string>
#include <fstream>
#include <windows.h>
#include <fstream>
#include <atlbase.h>
#include <windows.h>
#include <stdio.h>
using namespace std;
typedef std::basic_string<TCHAR> tstring;
FILE_ID_DESCRIPTOR getFileIdDescriptor(const DWORDLONG fileId)
{
FILE_ID_DESCRIPTOR fileDescriptor;
fileDescriptor.Type = FileIdType;
fileDescriptor.FileId.QuadPart = fileId;
fileDescriptor.dwSize = sizeof(fileDescriptor);
return fileDescriptor;
}
bool ReadMFT()
{
HANDLE hDevice = CreateFile(TEXT("\\\\.\\C:"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
printf("Error %d", GetLastError());
return (FALSE);
}
USN_JOURNAL_DATA ujd = { 0 };
DWORD cb = 0;
BYTE pData[sizeof(DWORDLONG) + 0x10000] = { 0 };
if (!DeviceIoControl(hDevice, FSCTL_QUERY_USN_JOURNAL, NULL, 0, &ujd, sizeof(USN_JOURNAL_DATA), &cb, NULL))
{
printf("Error %d", GetLastError());
return (FALSE);
}
MFT_ENUM_DATA med = { 0 };
med.StartFileReferenceNumber = 0;
med.LowUsn = 0;
med.HighUsn = ujd.NextUsn;
while (TRUE)
{
if (!DeviceIoControl(hDevice, FSCTL_ENUM_USN_DATA, &med, sizeof(med), pData, sizeof(pData), &cb, NULL))
{
printf("Error %d", GetLastError());
break;
}
PUSN_RECORD pRecord = (PUSN_RECORD)&pData[sizeof(USN)];
//Inner Loop
while ((PBYTE)pRecord < (pData + cb))
{
tstring sz((LPCWSTR)
((PBYTE)pRecord + pRecord->FileNameOffset),
pRecord->FileNameLength / sizeof(WCHAR));
pRecord = (PUSN_RECORD)((PBYTE)pRecord + pRecord->RecordLength);
// *******************************************************************************
// APPROACH 1
// Adding these lines of code increases the time from 25 seconds to 340 seconds
// Although it may be possible to push this onto a queue and run these in parrallel
// I still think it's an expensive option
/*TCHAR filePath[MAX_PATH];
HANDLE hh = OpenFileById(hDevice, &(getFileIdDescriptor(pRecord->FileReferenceNumber)), 0, 0, 0, 0);
GetFinalPathNameByHandle(hh, filePath, MAX_PATH, 0);*/
}
med.StartFileReferenceNumber = *(DWORDLONG *)pData;
}
}
int main()
{
ReadMFT();
}
Большое спасибо