Dのファイルに生のバイナリ構造を書き込みますか?
いくつかで定義されたいくつかのバイナリレコードを含むバイナリファイルを作成しようとしていますstruct
。しかし、私はそれを行う方法を見つけることができないようです。他の例を見ると、string
問題なくsを書くことができましたが、そうではありませんでしたstruct
。私はちょうど私がでするようにそれを書きたいC
とfwrite(3)
、しかしでD
バージョン2。
これが私がこれまでに試したことです:
- 使用して
stream.write(tr)
-人間が読める/デバッグ表現を書き込み、 - 使用
stream.rawWrite(tr)
-これは私が必要としているもののように聞こえましたが、コンパイルに失敗しました:
エラー:テンプレートstd.stdio.File.rawWriteは、引数タイプ!()(TitleRecord)から関数を推測できません。候補は次のとおりです。
/usr/lib/ldc/x86_64-linux-gnu/include/d/std/stdio.d(1132):std.stdio.File.rawWrite(T)(in T [] buffer)
rawWrite
上記のように試みますが、データをさまざまなものにキャストしても、コンパイルされることはありません。- さえに戻って取得しよう
C
とfwrite
しますが、ファイルディスクリプタIの必要性を得るために十分な深を取得することはできません。
ドキュメントを読むことはあまり役に立ちませんでした(文字列を書くことは私にとってもうまくいきますが、書くことはできませんstruct
)。簡単な方法があるはずですが、見つけることができません。他のSOの質問は 役に立ちませんでした。私はD 1.0
、それはで達成されたかもしれませんが、それはstream.writeExact(&tr, tr.sizeof)
もはや選択肢ではありません。
import std.stdio;
struct TitleRecord {
short id;
char[49] text;
};
TitleRecord tr;
void main()
{
auto stream = File("filename.dat","wb+");
tr.id = 1234;
tr.text = "hello world";
writeln(tr);
//stream.write(tr);
//stream.rawWrite(tr);
//stream.rawWrite(cast(ubyte[52]) tr);
//stream.rawWrite(cast(ubyte[]) tr);
//fwrite(&tr, 4, 1, stream);
}
回答
このため、そのエラーは、構造体ではなく配列を予期していることを示しています。したがって、これを行う簡単な方法の1つは、ポインターをスライスしてrawWriteに渡すことです。
stream.rawWrite((&tr)[0 .. 1]);
(&tr)
これポインタにあなたの構造体を変換し、アドレスを取得します。次に、[0 .. 1]
手段は最初からそのスライスを取得し、1つの要素だけを取得します。
これでT[]
、rawWriteが1つの要素を含めて処理できるようになりました。
@safe
これが渡されない注釈を使用する場合は、マークを付ける必要があることに注意してください@trusted
。またもちろん、構造体内の参照(を含むstring
)は、Cの経験から確かに知っているように、データではなくバイナリポインターとして書き込まれます。しかし、あなたがそこに示した場合、あなたは大丈夫です。
編集:ところで、必要にfwrite
応じて、Cから同じコードをコピーして貼り付けることもできます(foo.sizeof
代わりにある場合を除くsizeof foo
)。DのFile
ものはCの小さなラッパーでありFILE*
、元のFILE *を元に戻して他の関数に渡すことができます。stream.getFP()
http://dpldocs.info/experimental-docs/std.stdio.File.getFP.html )。
rawWrite
配列を期待しますが、多くの回避策があります。
1つは、単一の要素配列を作成することです。
file.rawWrite([myStruct]);
もう1つは、構造体を配列にキャストすることです。bitleveldと呼ばれる私のライブラリには、と呼ばれるそのための関数がありますreinterpretAsArray
。これにより、上記の構造体のチェックサムを簡単に作成することもできます。
この方法を使用した位置合わせで問題が発生することがありますので、注意してください。align
構造体のプロパティを変更することで修正できます。