1

数値データをバイナリ ファイルに書き込む必要があります。私が扱うデータ ベクトルの一部はサイズが数ギガになる可能性があるため、C++ iostream を使用しないことを学びました。代わりに、C ファイル* を使用したいと考えています。すぐに、バイナリ ファイルの先頭にメタ データを書き込む必要があるという問題に直面しています。一部のメタ データは最初は不明であるため、取得したメタ データをファイル内の適切なオフセットに追加する必要があります。

たとえば、年、月、日の uint16_t 表現を入力する必要があるとしますが、最初に最初のエントリ (精度の uint32_t 値) をスキップする必要があります。

何が間違っているのかわかりませんが、ファイルに「ab」を追加できないようです。これが私が書いたものの例です:

#include<cstdio>

uint16_t year = 2001;
uint16_t month = 8;
uint16_t day = 23;

uint16_t dateArray[]={year , month, day};

File * fileStream;
fileStream = fopen("/Users/mmmmmm/Desktop/test.bin" , "wb");

if(fileStream){

// skip the first 4 bytes
fseek ( fileStream , 4 , SEEK_SET );

fwrite(dateArray, sizeof(dateArray[0]) ,( sizeof(dateArray) / sizeof(dateArray[0]) ), filestream);

fclose(filestream);

}
 // loops and other code to prepare and gather other parameters

// ファイルの先頭に精度を追加します。

uint32_t precision = 32;

File *fileStream2;
fileStream2 = fopen("/Users/mmmmmm/Desktop/test.bin" , "ab"); 

if(fileStream2){

// Get to the top of the file
rewind(fileStream2);

fwrite(&precision, sizeof(precision) , 1 , fileStream2);

fclose(fileStream2);

}

追加されたデータは書き込まれません。「wb」に変更すると、ファイルが上書きされます。「r+b」で動作させることができましたが、その理由がわかりません。「ab」が適切だと思いました。また、バッファを使用する必要がありますか、それともこれで十分ですか?

アドバイスありがとう

ところで、これはMacOSX上にあります

4

3 に答える 3

3

ハードドライブとファイルシステムの仕組みにより、ファイルの途中にバイトを挿入すると非常に遅くなるため、特に数ギガバイトのファイルを扱う場合は避ける必要があります。メタデータが固定サイズのヘッダーに格納されている場合は、他のデータを開始する前に十分なスペースがあることを確認してください。ヘッダーのサイズが可変の場合は、ヘッダーをチャンクアップします。先頭に 1k のヘッダー スペースを配置し、次のヘッダー チャンクへのオフセットの値を格納するために 8 バイトを予約します。EOF の場合は 0 です。次に、そのチャンクがいっぱいになったら、別のチャンクをファイルの最後に追加し、そのオフセットを前のヘッダーに書き込みます。

テクニカル IO については、必要に応じて、、またはのfopen()モードを使用します。それらはすべて同じように動作しますが、わずかな違いがあります。最初のバイトから読み書きできるようにファイルを開きます。ファイルが存在しない場合はエラーになります。同じことを行いますが、ファイルが存在しない場合は作成します。と同じですが、ファイルの末尾にあるファイル ポインターから始まります。r+bw+ba+br+bw+ba+br+b

fseek()とでファイルをナビゲートできますrewind()rewind()ファイルポインタをファイルの先頭に戻します。fseek()ファイルポインタを指定された場所に移動します。詳細については、こちらをご覧ください。

于 2012-08-24T08:42:41.073 に答える
1

「r+b」は、ファイル内の任意の位置に読み書きできることを意味します。2 番目のコード ブロックでは、rewind() 呼び出しによって現在の位置がバイト 0 に設定され、書き込みはこの位置で行われます。

「a+b」を使用する場合、これは読み取りおよび書き込みアクセスも意味しますが、書き込みはすべてファイルの最後にあるため、新しい空のファイルが作成されない限り、バイト 0 に配置することはできません。

特定のバイトでファイルに再度アクセスするには、fseek() を使用します。

fseek ( fileStream , 0 , SEEK_SET ); - 精度値への位置

fseek ( fileStream , 4 , SEEK_SET ); - 年値への位置

fseek (ファイルストリーム、8、SEEK_SET); - 月の値へのポジション

fseek ( fileStream , 12 , SEEK_SET ); - 日の値へのポジション

于 2012-08-24T08:02:43.233 に答える
0

このような大きなファイルでは、ギグを書き直して数バイトを先頭に追加するだけでは非常に非効率的です。

各ファイルに必要なメタデータの小さなコンパニオン ファイルを作成し、メタデータ フィールドを編集の一部として書き換える場合にのみ、ファイルの先頭に追加する方がはるかに優れています。

これは、ほとんどのファイル システムで、ファイルの前に追加すると非常にコストがかかるためです。NTFS には、ファイル マネージャやセキュリティ スキャン プログラムなどの MS 内部のプログラムを除いて、ほとんどすべてのプログラムから見えないほとんどのファイル用の 2 番目のデータ チャネルがあります。ディスク上のギグを毎回上書きすることなく、メタデータをそのチャネルに追加するプログラムを簡単に作成できます。

于 2020-10-03T20:04:42.153 に答える