C/C++中从二进制文件中间读取和写入数据

6
如果我有一个大的二进制文件(假设它有1亿个浮点数),在C(或C ++)中是否有一种方法可以打开文件并读取特定的浮点数,而无需将整个文件加载到内存中(即如何快速找到第62,821,214个浮点数)?第二个问题是,是否有一种方法可以更改该文件中的特定浮点数,而不必重写整个文件?
我想象中的函数如下:
float readFloatFromFile(const char* fileName, int idx) {
    FILE* f = fopen(fileName,"rb");

    // What goes here?
}

void writeFloatToFile(const char* fileName, int idx, float f) {
    // How do I open the file? fopen can only append or start a new file, right?

    // What goes here?
}

在编写时,请确保以“r+”模式打开,而不是“a+”模式。在追加模式下,无论您寻找的位置在哪里,写入始终会到达文件的末尾。 - Edward Anderson
5个回答

20
你知道浮点数的大小是sizeof(float),所以乘法可以让你到达正确的位置:
FILE *f = fopen(fileName, "rb");
fseek(f, idx * sizeof(float), SEEK_SET);
float result;
fread(&result, sizeof(float), 1, f);

同样地,你可以使用这个方法写入到特定位置。


好的,应该是fread(&result, sizeof(result), 1, f);,对吧? - Switch

4

3

如果您想使用C++流,这里有一个示例:

#include <fstream>
using namespace std;

int main()
{
    fstream file("floats.bin", ios::binary);
    float number;

    file.seekp(62821214*sizeof(float), ios::beg);
    file.read(reinterpret_cast<char*>(&number), sizeof(float));
    file.seekp(0, ios::beg); // move to the beginning of the file
    number = 3.2;
    // write number at the beginning of the file
    file.write(reinterpret_cast<char*>(&number), sizeof(float));
}

0

我知道这个问题已经有答案了,但是Linux/Unix提供了易于使用的系统调用来在文件中间进行读写(pread/pwrite)。如果你查看系统调用“read”和“pread”的内核源代码,它们最终都会调用vfs_read()。而vfs_read需要一个偏移量,即它需要从文件中读取的位置。在pread中,这个偏移量由我们给出,在read()中,偏移量在内核中被计算并为文件描述符维护。与read()相比,pread()提供了卓越的性能,并且使用pread(),您可以在同一文件描述符中的多个线程中同时读写文件的不同部分。我的谦逊意见是,永远不要使用read()或其他文件流,使用pread()。希望文件流库已经封装了read()调用,通过少量的系统调用来实现高效的流操作。

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
  char* buf; off_t offToStart = id * sizeof(float); size_t sizeToRead = sizeof(float);
  int fd = open("fileName", O_RDONLY);
  ret = pread(fd, buf, sizeToRead, offToStart);
  //processs from the read 'buf'
  close(fd);
}

0

一种方法是在文件上调用mmap()。完成后,您可以像处理内存数组一样读取/修改文件。

当然,如果文件太大而无法适应进程的地址空间,则该方法仅适用于...如果您正在以64位模式运行,则没有问题;在32位模式下,具有100,000,000个浮点数的文件应该适合,但超过这个数量级,您可能会遇到麻烦。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接