[英]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.