【问题标题】:How to read blocks of data from a file and then read from that block into a vector?如何从文件中读取数据块,然后从该块读取到向量中?
【发布时间】:2013-02-28 05:50:03
【问题描述】:

假设我有一个包含 x 条记录的文件。一个“块”保存 m 条记录。文件中的总块数 n=x/m。如果我知道一条记录的大小,比如 b 字节(一个块的大小 = b*m),我可以使用系统命令 read() 一次读取完整的块(还有其他方法吗?)。现在,我如何从这个块中读取每条记录,并将每条记录作为一个单独的元素放入一个向量中。

我之所以要这样做,首先是为了减少磁盘 i/o 操作。根据我所学到的,由于磁盘 i/o 操作要昂贵得多。 还是与我从文件中逐条读取记录并直接将其放入向量而不是逐块读取时所花费的时间相同?在逐块读取时,我将只有 n 个磁盘 I/O,而如果我逐条读取,我将有 x 个 I/O。

谢谢。

【问题讨论】:

    标签: c++ database memory memory-management


    【解决方案1】:

    您应该考虑使用mmap() 而不是使用read() 读取文件。

    mmap 的好处在于,您可以将文件内容视为简单地映射到您的进程空间,就好像您已经拥有指向文件内容的指针一样。通过简单地检查内存内容并将其视为一个数组,或者通过使用memcpy() 复制数据,您将隐式执行读取操作,但仅在必要时 - 操作系统虚拟内存子系统足够智能,可以非常高效地执行此操作。

    避免 mmap 的唯一可能原因可能是您在 32 位操作系统上运行并且文件大小超过 2 GB(或略小于该大小)。在这种情况下,操作系统可能无法为您的mmap-ed 内存分配地址空间。但在 64 位操作系统上,使用 mmap 绝对不是问题。

    另外,mmap 可能会很麻烦,如果您要写入大量数据,并且预先不知道数据的大小。除此之外,在read 上使用它总是更好更快。

    实际上,大多数现代操作系统都广泛依赖mmap。例如,在 Linux 中,要执行一些二进制文件,您的可执行文件只需 mmap-ed 并从内存中执行,就好像它是由 read 复制到那里一样,实际上并没有 reading 它。

    【讨论】:

      【解决方案2】:

      一次读取一个块并不一定会减少 I/O 操作的数量。标准库在从文件中读取数据时已经进行了缓冲,因此您(通常)希望每次尝试从流中读取(或任何接近的数据)时都会看到实际的磁盘输入操作.

      一次读取一个块仍然可能会减少 I/O 操作的数量。如果您的块大于流默认使用的缓冲区,那么您会看到用于读取数据的 I/O 操作更少。另一方面,您可以通过简单地调整流使用的缓冲区大小来完成相同的操作(这可能要容易得多)。

      【讨论】:

      • 您好,感谢您的回复。所以为了清楚起见,你的意思是说我第一次调用“getline(file_pointer,str)”时,C++ 已经隐式地将包含这一行的块从硬盘带到内存?因此,我第二次读取一行时,不会执行磁盘 I/O,而是从主内存中读取该行(假设两行位于同一块中)?
      • 此外,块大小可以大到 2-3 mb。缓冲区大小一样大吗?我们如何增加缓冲区大小?
      • @NikharAgrawal:是的,当您调用 getline 时,它​​可能会从磁盘读取类似 8K 的数据,然后向您发送(比如说)构成该行的 60 个字节。是的,在 8K 用完之前,它不会再次从磁盘读取。但也可以,它可能是 4-16KB,而不是 2-3 MB。
      • 谢谢。 :) 关于我们如何在 C++ 中实际增加缓冲区大小的任何想法?
      • @NikharAgrawal:哎呀,对不起。 yourstream.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多