2009-11-08 26 views
6

大きなバイナリファイル(例えば100,000,000の浮動小数点数)がある場合、C(またはC++)でファイルを開き、ファイル全体をメモリにロードする必要はありません(つまり、62,821,214浮動小数点数はどのようにすばやく見つけることができますか)。もう1つ質問ですが、ファイル全体を書き直すことなくファイル内の特定のfloatを変更する方法はありますか?C/C++でのバイナリファイルの読み書き

ように私は、関数を想定しています。同様に

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

、あなたが書くことができます:あなたはフロートのサイズはsizeof(float)ので、乗算は正しい位置にあなたを得ることができます知っている

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? 
} 
+0

書き込みについては、「+」ではなく「r +」モードで開いてください。追加モードでは、どこにシークしても、書き込みは常にファイルの最後に移動します。 –

答えて

19

このメソッドを使用して特定の位置に移動します。

+0

大丈夫です。それはfread(&result、sizeof(result)、1、f)でなければなりません。でもね? – Switch

+0

ああ、あなたは大丈夫です。私はそれを修正します。 –

4

fopenはfopenrb+またはwb+モードを使用してファイルを変更するだけでなく、追加することもできます。ここを参照してください:http://www.cplusplus.com/reference/clibrary/cstdio/fopen/

特定のフロートにファイルを配置するには、あなたがorignとしてオフセット広告SEEK_SETとしてindex*sizeof(float)を使用してfseekを使用することができます。ここを参照してください:あなたがC++ストリームを使用したい場合はここでhttp://www.cplusplus.com/reference/clibrary/cstdio/fseek/

+0

"rb +"は動作しますが、 "wb +"は存在する場合にファイルを切り捨てます – marcin

3

は一例です:

#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

一つの方法は、ファイルにmmap()を呼び出すことであろう。これを実行すると、あたかもメモリ内の配列であるかのようにファイルを読み書きすることができます。

もちろん、この方法は、ファイルがプロセスのアドレス空間に収まるほど小さい場合にのみ機能します。64ビットモードで実行している場合は問題ありません。 32ビットモードでは、100,000,000の浮動小数点数を持つファイルが収まるはずですが、それ以上のオーダーまたは2倍の大きさで問題が発生する可能性があります。

-1

私はこの質問が既に答えられていることを知っていますが、Linux/Unixはファイルの途中で読み書き(pread/pwrite)するための簡単なシステムコールを提供します。システムコールのカーネルソースコード '&' pread 'を呼び出すと、最終的にvfs_read()が呼び出されます。また、vfs_readにはOFFSETが必要です。つまり、ファイルから読み込むにはPOSITIONが必要です。 preadでは、このオフセットは私たちによって与えられ、read()ではオフセットはカーネルで内部的に計算され、ファイル記述子のために保持されます。 pread()はread()と比較して優れたパフォーマンスを提供し、preadを使用すると、ファイルの異なる部分の複数のスレッドで同じファイル記述子を同時に読み書きすることができます。私の謙虚な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); 
} 
+0

この解決策ではバイナリファイルを読み取ることができません。 – LOLKFC

関連する問題