繁体   English   中英

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

[英]Reading from and writing to the middle of a binary file in 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?
}

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

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

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

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

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

如果您想使用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));
}

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

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

我知道这个问题已经得到解答,但Linux / Unix提供了在文件中间轻松读/写(pread / pwrite)的系统调用。 如果你查看系统调用'read'和'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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM