次の例では、メモリ内で32バイトを占有する構造体を取得し、それをファイルに書き込んで読み戻します。つまり、データをバイナリ形式にシリアル化します。
#include <stdio.h>
typedef struct _Person {
char name[20];
int age;
double weight;
} Person;
int main(void)
{
Person tom = (Person) {.name="Tom", .age=20, .weight=125.0};
// write the struct to a binary file
FILE *fout = fopen("person.b", "wb");
fwrite(&tom, sizeof tom, 1, fout);
fclose(fout);
// read the binary data and set the person to that
Person unknown;
FILE *fin = fopen("person.b", "rb");
fread(&unknown, sizeof unknown, 1, fin);
fclose(fin);
// confirm all looks ok
printf("{name=%s, age=%d, weight=%f}", unknown.name, unknown.age, unknown.weight);
}
ただし、これらはすべてスタック上の値であり、ポインター/間接参照は含まれないことに注意してください。たとえば、複数のポインタが含まれる可能性がある場合、複数の変数が同じメモリ位置を指す場合など、データをファイルにシリアル化するにはどうすればよいでしょうか。これは事実上、プロトコルバッファが行うことですか。
さて、バイナリファイルが必要です。私はずっと前にこのようにそれをしていました。大丈夫だよ。別のプラットフォームやビットネスに移動すると、壊れてしまいます。始めるのに良い場所なので、私は古い方法を教えています。プラットフォームやビットネスを変更するときに機能し続けるため、新しい方法が現在人気があります。
ファイルにレコードを書き込むときは、次のような構造体を使用します。
typedef struct _Person {
char name[20];
int age;
double weight;
} Person;
typedef struct _Thing {
char name[20];
};
typedef struct _Owner {
int personId;
int thingId;
} Owner;
Owner
構造にIdメンバーがどのように含まれているかを確認してください。これらは、他の構造の配列への単なるインデックスです。
これらは次々にファイルに書き出すことができ、通常、各種類のレコードの数を示す直接書き込まれた単一の整数が接頭辞として付けられます。リーダーは、malloc
それらを保持するのに十分な大きさの構造体の配列を割り当てるだけです。メモリにアイテムを追加するときに、配列のサイズをrealloc
。で変更します。削除(たとえば、名前の最初の文字を0に設定することによって)および後でレコードを再利用するためにマークを付けることもできます(そしてそうすべきです)。
ライターは次のようになります。
void writeall(FILE *h, Person *allPeople, int nPeople, Thing *allThings, int nThings, Owner *allOwners, int nOwners)
{
// Error checking omitted for brevity
fwrite(&nPeople, sizeof(nPeople), 1, h);
fwrite(allPeople, sizeof(*allPeople), nPeople, h);
fwrite(&nThings, sizeof(nThings), 1, h);
fwrite(allThings, sizeof(*allThings), nThings, h);
fwrite(&nOwners, sizeof(nOwners), 1, h);
fwrite(allOwners, sizeof(*allOwners), nOwners, h);
}
リーダーは次のようになります。
int writeall(FILE *h, Person **allPeople, int *nPeople, int *aPeople, Thing **allThings, int *nThings, int *aThings, Owner **allOwners, int *nOwners, int *aOwners)
{
*aPeople = 0; // Don't crash on bad read
*aThigns = 0;
*aOwners = 0;
*allPeople = NULL;
*allThings = NULL;
*allOwners = NULL;
if (1 != fread(nPeople, sizeof(*nPeople), 1, h)) return 0;
*allPeople = malloc(sizeof(**allPeople) * *nPeople);
if (!allPeople) return 0; // OOM
*aPeople = *nPeople;
if (*nPeople != fread(*allPeople, sizeof(**allPeople), nPeople, h)) return 0;
if (1 != fread(nThings, sizeof(*nThings), 1, h)) return 0;
*allThings = malloc(sizeof(**allThings) * *nThings);
if (!allThings) return 0; // OOM
*aThings = *nThings;
if (*nThings != fread(*allThings, sizeof(**allThings), nThings, h)) return 0;
if (1 != fread(nOwners, sizeof(*nOwners), 1, h)) return 0;
*allOwners = malloc(sizeof(**allOwners) * *nOwners);
if (!allOwners) return 0; // OOM
*aOwners = *nOwners;
if (*nOwners != fread(*allOwners, sizeof(**allOwners), nOwners, h)) return 0;
return 1;
}
ヒープアリーナをディスクに直接書き込み、それを再度読み取るための古い手法がありました。絶対に使用せず、ポインタをディスクに保存しないことをお勧めします。そのように、セキュリティの悪夢があります。
メモリが安価だったときは、ブロック割り当てとリンクされたブロックを使用して、ディスク上のレコードを部分的に動的に更新する方法について話していました。しかし、このレベルで発生する問題については、気にしないで、すべてをRAMに読み込んで、再度書き戻すだけです。最終的には、データベースを学習します。データベースは、そのようなものを処理します。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加