在C / C ++中读取和写入二进制文件的中间

时间:2009-11-08 07:41:17

标签: c++ c

如果我有一个大的二进制文件(比如它有100,000,000个浮点数),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?
}

5 个答案:

答案 0 :(得分:19)

你知道浮点数的大小是sizeof(float),所以乘法可以让你到达正确的位置:

FILE *f = fopen(fileName, "rb");
fseek(f, idx * sizeof(float), SEEK_SET);
float result;
fread(&result, sizeof(float), 1, f);

同样,您可以使用此方法写入特定位置。

答案 1 :(得分:4)

fopen允许使用rb+上的wb+fopen模式打开文件进行修改(而不仅仅是追加)。见这里:http://www.cplusplus.com/reference/clibrary/cstdio/fopen/

要将文件定位到特定的浮动广告,您可以使用fseek作为偏移广告index*sizeof(float)作为预设使用SEEK_SET。见这里:http://www.cplusplus.com/reference/clibrary/cstdio/fseek/

答案 2 :(得分: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));
}

答案 3 :(得分:0)

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

当然,只有当文件足够小以适应进程的地址空间时,该方法才有效...如果你在64位模式下运行,你会没事的;在32位模式下,一个包含100,000,000个浮点数的文件应该适合,但是高于该数量的另一个或两个数量级,您可能会遇到麻烦。

答案 4 :(得分:-1)

我知道这个问题已经得到解答,但Linux / Unix提供了在文件中间轻松读/写(pread / pwrite)的系统调用。如果你看一下系统调用'read'&amp ;;的内核源代码。 'pread',最终都调用vfs_read()。而vfs_read需要一个OFFSET,即它需要一个POSITION来从文件中读取。在pread中,这个偏移量由我们给出,在read()中,偏移量在内核中计算并为文件描述符维护。与read()和pread相比,pread()提供了出色的性能,您可以在文件的不同部分的多个线程中同时读取/写入相同的文件描述符。我的Humble opionion,从不使用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);
}