【问题标题】:Reading through files quickly [closed]快速阅读文件[关闭]
【发布时间】:2013-10-16 12:40:48
【问题描述】:

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

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

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

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

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

您能提出任何替代方案吗?

编辑

文件格式:

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

【问题讨论】:

  • 你想用它做什么?文件格式是什么?
  • 是什么让您认为您不受 I/O 限制?你分析过它吗?
  • 啊,还没有,但是如果你用 3.5 秒来划分 50MB,这真的没有意义......另外,我已经在 4 台不同的 PC 上测试过......
  • 呃。这是本周第二次有人认为一个小例子是对他们文件格式的全面描述。例如,这些可以是由任意数量的任何其他字符分隔的任何十进制数字字符串(可能带有 + 或 -),或者它们可以是严格的正十进制数,保证在此平台上可以由 int 表示,严格分隔由一个空格字符。
  • 获得更快的硬盘?没有人可能希望回答这个问题,因为算法运行所需的秒数完全取决于您的硬件、操作系统、编译器和其他环境因素。

标签: c++ c file input scanf


【解决方案1】:

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

CreateFileMapping
MapViewOfFile

【讨论】:

  • 这不是一个真正的答案,它应该是一个评论。另外,(s?)他没有说正在使用哪个平台。不是每个人都使用 Windows!但无论如何,如果我理解正确的话,那并不能真正“读取”文件。它使它“看起来”像内存,但是您仍然需要检查整个事情,将其从磁盘拉到内存,以解析整数(尽管这可能会更快)。
  • 他。而且我同时使用 Win 和 Linux...
【解决方案2】:

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

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

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

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

有很多优化方法:

  • 单个大缓冲区——将大量数据读入单个缓冲区并 解析缓冲区。
  • 双缓冲或多缓冲 -- 使用多个缓冲区,所以一个 一个线程可以解析一个缓冲区,而另一个线程将数据读入 另一个缓冲区。
  • 内存映射文件 -- 操作系统管理文件读取,就好像它是 记忆。

程序之外的其他方法:

  • 使用fixed优化文件数据结构,实现高效读取 记录大小。
  • 减少文件中的碎片数量——瞄准一个巨大的 硬盘驱动器上的连续区域。

【讨论】:

    【解决方案3】:

    为什么这个文件包含什么很重要?使用这个非常又快又脏的标准 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 bytes\n", (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)
    

    警告:在 same 文件上再次运行它会返回:

    successfully read 54721618 bytes
    this took 0.037000 second(s)
    

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

    【讨论】:

    • 其实确实可以很快....不过,我只需要不到 1 秒的时间读取数据,处理时间几乎可以忽略不计。
    • @user2886385:所以你接受我的解决方案?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-05
    • 1970-01-01
    相关资源
    最近更新 更多