子:バイナリ ファイルへの文字列の書き込みとバイナリ ファイルからの文字列の読み取り
-
19-09-2019 - |
質問
文字列を他の多くのデータとともにバイナリファイルに保存したいのですが、以下のコードを使用しています(実際に使用すると文字列はmallocされます)。ファイルに書き込むことができます。16進エディタで見てみました。null ターミネータを正しく書いているかどうか (または必要かどうか) がわかりません。読み戻すと、保存したのと同じ文字列長が得られますが、文字列は得られません。私は何を間違っているのでしょうか?
FILE *fp = fopen("mybinfile.ttt", "wb");
char drumCString[6] = "Hello\0";
printf("%s\n", drumCString);
//the string length + 1 for the null terminator
unsigned short sizeOfString = strlen(drumCString) + 1;
fwrite(&sizeOfString, sizeof(unsigned short), 1, fp);
//write the string
fwrite(drumCString, sizeof(char), sizeOfString, fp);
fclose(fp);
fp = fopen("mybinfile.ttt", "rb");
unsigned short stringLength = 0;
fread(&stringLength, sizeof(unsigned short), 1, fp);
char *drumReadString = malloc(sizeof(char) * stringLength);
int count = fread(&drumReadString, sizeof(char), stringLength, fp);
//CRASH POINT
printf("%s\n", drumReadString);
fclose(fp);
解決
あなたは読みながら間違ってやっています。 あなたはそれがセグメンテーションフォールトを与える理由ですポインタ変数に&を入れている。
私はそれが正常に動作し、それが正しくこんにちは返すことを取り除いています。
int count = fread(drumReadString, sizeof(char), stringLength, fp);
他のヒント
いくつかの問題があり、いくつかは問題があり、いくつかはスタイル的に問題があると思います。
- 本当にからの戻り値をテストする必要があります
malloc
,fread
そしてfwrite
割り当てが失敗し、データの読み取りまたは書き込みが行われない可能性があるためです。 sizeof(char)
は いつも 1、掛ける必要はありません。- 文字配列
"Hello\0"
実際の長さは 7 バイトです。余分な null ターミネータを追加する必要はありません。 - 私はそのイディオムの方が好きです
char x[] = "xxx";
明確な長さを指定するのではなく (もちろん、文字列よりも長い配列が必要な場合を除きます)。 - あなたが
fread(&drumReadString ...
, 、実際には上書きしています ポインタ, 、それが指すメモリではありません。これがクラッシュの原因です。そのはずfread(drumReadString ...
.
のヒントをいくつます:
1
終端\0
は、任意の二重引用符文字列に暗黙的で、そして最後に、追加を追加することによって、次の2つで終わります。次の二つの初期化は同じです。
char str1[6] = "Hello\0";
char str2[6] = { 'H', 'e', 'l', 'l', 'o', '\0', '\0'};
だから、
char drumReadString[] = "Hello";
は十分であり、それは次のように初期化されるとき、配列のサイズを指定するオプションで、コンパイラは、必要なサイズ(6バイト)を把握します。
2
の文字列を書くとき、あなただけのようにもちょうど(代わりに1文字sizeOfString回ずつ書く)一度のすべての文字を書きます。
fwrite(drumCString, sizeOfString, 1, fp);
3
であっても、通常のデスクトップPCのシナリオについてそれほど一般的ではないものの、malloc関数はNULLを返すことができますし、組み込み環境では、NULLを取得する可能性は低い結果ではありませんので、必ず結果を確認するhabbitの開発の恩恵を受けるます。
char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
fprintf(stderr, "drumReadString allocation failed\n");
return;
}
あなたは終端のヌルを書いていない、あなたがする必要はありませんが、その後、あなたは読んだときにそれを追加することについて考える必要があります。つまり、malloc関数StringLengthに+ 1つの文字、StringLengthのの文字を読み込み、読み込まれたものの終わりに\0
を追加します。
今通常の警告:あなたはバイナリファイルにあなたがここでやっている方法を記述している場合は、時には同じコンパイラの別のバージョンに、ポートへのあなたのフォーマットを困難にする暗黙の仮定の多くを持っている - 私が見てきましたコンパイラのバージョン間の構造体の変更のデフォルトのアライメントます。
より多くのいくつかはpaxdiabloするために追加しAProgrammerする - あなたは、将来的にmalloc関数を使用しようとしている場合は、ちょうど行きますから、それを行います。それは、より良い形だとあなたが切り替わるときにデバッグする必要がないことを意味します。
あなたがバイナリファイルを書き込むことを計画している場合は、また、私は完全に、符号なしshortの使用を見ていないよ、unsigned char型は、その目的のために、それは非常に便利に、サイズのバイトの一般的であると考えます。
あなただけのガネーシャmentioned.Because、drumReadStringはarray.Arrayが直接メモリ位置を指し示すポインタに似ている通りである。
単にその機能にdrumReadStringを使うのfread function.Youであなた&drumReadStringを削除します