【问题标题】:What is the fastest way to read a file in disk in c++?在 C++ 中读取磁盘中文件的最快方法是什么?
【发布时间】:2015-05-29 23:50:12
【问题描述】:

我正在编写一个程序来检查文件是否为 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;
}

提前致谢。

【问题讨论】:

  • 您是否尝试过使用 C 的 FILE 或 C++ fstream 看看它们是否足够快?
  • 如果您的问题是关于 C++ 的,为什么您的问题会被标记为 c?这没有任何意义,儿子。
  • 什么是creatfile和readfile?
  • 很难说什么是最快的——它可能取决于各种因素,例如驱动器的固件、寻道时间、操作系统版本等。我怀疑它们之间会有很大差异,但是如果我是你并且真的在乎,我会进行基准测试以将ifstream 与内存映射进行比较(如果你不想自己编写代码,boost 有一个实现)。
  • 你在制造病毒吗? ))

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


【解决方案1】:

我认为您遇到了机械硬盘驱动器的固有限制。您没有提到您使用的是 HDD 还是固态磁盘,但鉴于您的文件访问速度很慢,我假设是 HDD。

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

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

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

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

【讨论】:

  • 问题确实是硬件。此处描述的问题是机械 HDD 缺少“随机 IOPS”(每秒 I/O 操作)。
  • 感谢@juhist 的回答。
【解决方案2】:

为了更快的文件 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 快。

【讨论】:

  • 很确定 CreateFile / ReadFile 是 OP 所说的“太慢”。
  • 我提到了重叠或 IOCP。
  • “我认为 C 和 C++ 的 FILE 和 fstream 分别并不比 Win32 快” - 事实上,C++ 文件流很可能只是使用 C 流,这肯定是使用 Win32 文件 API 实现。
猜你喜欢
  • 1970-01-01
  • 2010-11-08
  • 2011-02-02
  • 2013-10-24
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多