快速阅读文件

Reading through files quickly

本文关键字:文件      更新时间:2023-10-16

我的问题是:如何使用C++或C程序快速读取超过50 MB 的文件(即大约一秒钟内)...

我感兴趣的是文件,其中包含纯整数...

我已经排除了 ifstream,因为它对于这个目的来说太慢了(8-9 秒)。

目前,我正在使用 fscanf,但它仍然非常非常慢(4 秒)....

我 100% 确定读取文件的方式是问题所在,并且我没有 I/O 限制。

你能建议任何替代方案吗?

编辑

文件格式:

1 2 41 2 1 5 1 2 ... (integers)

尝试使用内存映射文件。尝试谷歌搜索

CreateFileMapping
MapViewOfFile

为了更快地读取数据,您必须减少读取量并增加读取数据量。

假设最坏的情况,硬盘驱动器必须为每个读取命令初始化:

  • 拼盘必须跟上速度(需要时间)。
  • 操作系统读取目录结构。
  • 操作系统会在目录结构中搜索您的文件。
  • 操作系统告诉硬盘驱动器要读取哪个扇区或盘片和扇区从。
  • 硬盘等待扇区启动,然后读取来自该部门开始的连续数据。
  • 硬盘降速。

除了从该行业读取之外,其他所有内容都被视为开销。 无论读取一个字节还是读取 10k,都将应用开销。 效率是保持驱动器旋转,这意味着每个"读取"命令读取更多数据。

有许多方法可以优化这一点:

  • 单个大型缓冲区 -- 将大量数据读入单个缓冲区,并且分析缓冲区。
  • 双缓冲或多重缓冲 -- 使用多个缓冲器,以便一个线程可以解析一个缓冲区,而另一个线程将数据读取到另一个缓冲区。
  • 内存映射文件 -- 操作系统像管理文件读取一样管理文件记忆。

程序之外的其他方法:

  • 优化文件数据结构,使用固定记录大小。
  • 减少文件中的片段数量 - 瞄准一个巨大的硬盘上的连续区域。

为什么这个文件包含什么很重要?使用这个非常快速和肮脏的标准 C 程序读取一个 54Mb 文件需要半秒钟:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
unsigned char *big_file = NULL;
size_t length;
int main(int argc, char **argv)
{
    FILE *f;
    clock_t start_time, end_time;
    if (argc >= 2)
    {
        start_time = clock();
        f = fopen (argv[1], "rb");
        if (f)
        {
            fseek (f, 0, SEEK_END);
            length = ftell(f);
            fseek (f, 0, SEEK_SET);
            big_file = (unsigned char *)malloc(length);
            if (big_file)
            {
                if (fread (big_file, 1,length, f) == length)
                    printf ("successfully read %lu bytesn", (unsigned long)length);
                free (big_file);
            }
            fclose (f);
        }
        end_time = clock() - start_time;
        printf ("this took %f second(s)n", ((double)end_time)/CLOCKS_PER_SEC);
    }
}

输出:

successfully read 54721618 bytes
this took 0.523000 second(s)

请注意:在同一文件上再次运行它会返回以下内容:

successfully read 54721618 bytes
this took 0.037000 second(s)

有了这个,你的问题可能需要改写:"好的,这样我就可以快速阅读,但我需要对这些数据做XXX"——如果"XXX"="很多",你可能会超过1秒时间分配内剩余的0.477秒。