3

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

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

谢谢。

4

2 回答 2

3

您应该考虑使用mmap()而不是使用read().

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

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

此外,mmap如果您要写入大量数据,并且预先不知道数据的大小,这可能会很麻烦。除此之外,在read.

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

于 2013-02-28T06:13:07.593 回答
2

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

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

于 2013-02-28T05:57:57.683 回答