簡體   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