在c ++中读取磁盘文件的最快方法是什么?

时间:2015-03-26 03:03:02

标签: c++ c winapi visual-c++ readfile

我正在编写一个程序来检查文件是否是PE文件。为此,我只需要读取文件的文件头(我想这不会超过文件的前1024个字节)。

我尝试使用creatfile()+ readfile()组合,结果会变慢,因为我正在遍历系统驱动器中的所有文件。只需要15-20分钟来迭代它们。

您能告诉我们打开和阅读文件的其他方法,以加快速度吗?

注意:请注意我不需要完整阅读该文件。我只需要读取文件的初始部分 - DOS标头,PE标头等,我猜这个文件的前512字节不会超过。

这是我的代码:

bool IsPEFile(const String filePath)
{
    HANDLE hFile = CreateFile(filePath.c_str(),
    GENERIC_READ,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL);

DWORD dwBytesRead = 0;
const DWORD CHUNK_SIZE = 2048;
BYTE szBuffer[CHUNK_SIZE] = {0};
LONGLONG size;
LARGE_INTEGER li = {0};
if (hFile != INVALID_HANDLE_VALUE)
{       
    if(GetFileSizeEx(hFile, &li) && li.QuadPart > 0)
    {
        size = li.QuadPart;
        ReadFile(hFile, szBuffer, CHUNK_SIZE, &dwBytesRead, NULL);
        if(dwBytesRead > 0 && (WORDPTR(szBuffer[0]) == ('M' << 8) + 'Z' || WORDPTR(szBuffer[0]) == ('Z' << 8) + 'M'))
        {
            LONGLONG ne_pe_header = DWORDPTR(szBuffer[0x3c]);
            WORD signature = 0;
            if(ne_pe_header <= dwBytesRead-2) 
            {
                signature = WORDPTR(szBuffer[ne_pe_header]);
            }
            else if (ne_pe_header < size )
            {
                SetFilePointer(hFile, ne_pe_header, NULL, FILE_BEGIN);
                ReadFile(hFile, &signature, sizeof(signature), &dwBytesRead, NULL);
                if (dwBytesRead != sizeof(signature))
                {
                    return false;
                }
            }
            if(signature == 0x4550) // PE file
            {
                return true;
            }
        }
    }
    CloseHandle(hFile);
}
return false;
}

提前致谢。

2 个答案:

答案 0 :(得分:2)

我认为您正在克服机械硬盘驱动器的固有局限性。您没有提及您是使用硬盘还是固态硬盘,但我认为您的文件访问速度很慢,我认为是硬盘。

HDD可以按顺序以大约100 MB / s的速度读取数据,但寻道时间有点超过10 ms。这意味着如果您寻找某个位置(10毫秒),您也可以读取一兆字节的数据(另一个10毫秒)。这也意味着您每秒只能访问少于100个文件。

因此,在您的情况下,您是否正在读取文件的前512个字节或文件的前100字节并不重要。

硬件便宜,程序员时间昂贵。如果文件访问速度太慢,最好的办法是购买固态磁盘驱动器。我预测最终所有计算机都将拥有固态磁盘驱动器。

注意:如果瓶颈是硬盘驱动器,除了用更好的技术更换硬盘驱动器之外,你无能为力。实际上所有文件访问机制都同样慢。你唯一能做的就是只读取文件的初始部分,如果文件非常大,例如多兆字节。但根据您的代码示例,您已经这样做了。

答案 1 :(得分:-1)

要获得更快的文件IO,您需要使用Win32的CreateFileReadFile API。 如果您想加快速度,可以使用文件缓冲并使用重叠的IO或IOCP使文件无阻塞。

请参阅此示例以获取帮助:https://msdn.microsoft.com/en-us/library/windows/desktop/bb540534%28v=vs.85%29.aspx

我认为C和C ++的FILEfstream分别不比Win32快。