Menulis struktur biner mentah ke file dalam D?
Saya mencoba memiliki file biner yang berisi beberapa catatan biner yang didefinisikan di beberapa struct. Namun, sepertinya saya tidak dapat menemukan cara melakukannya. Melihat contoh lain, saya berhasil menulis stringtanpa masalah, tetapi tidak struct. Aku hanya ingin menulis seperti aku akan di Cdengan fwrite(3), tetapi dalam Dversi 2.
Inilah yang saya coba sejauh ini:
- menggunakan
stream.write(tr)- menulis representasi yang dapat dibaca / debug manusia - menggunakan
stream.rawWrite(tr)- ini terdengar seperti yang saya butuhkan, tetapi gagal untuk dikompilasi dengan:
Kesalahan: template std.stdio.File.rawWrite tidak dapat menyimpulkan fungsi dari tipe argumen! () (TitleRecord), kandidatnya adalah:
/usr/lib/ldc/x86_64-linux-gnu/include/d/std/stdio.d(1132): std.stdio.File.rawWrite (T) (dalam buffer T [])
- mencoba
rawWriteseperti di atas, tetapi mentransmisikan data ke berbagai hal, juga tidak pernah mengkompilasi. - bahkan mencoba untuk kembali ke
Cdenganfwrite, tetapi tidak bisa cukup dalam untuk mendapatkan deskriptor file yang saya butuhkan.
Membaca dokumen tidak terlalu membantu (menulis string juga berfungsi untuk saya, tetapi tidak menulis struct). Saya yakin pasti ada cara sederhana untuk melakukannya, tetapi saya tidak dapat menemukannya .... Pertanyaan SO lainnya tidak membantu saya . Saya D 1.0, itu mungkin telah tercapai stream.writeExact(&tr, tr.sizeof)tetapi itu bukan lagi pilihan.
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);
}
Jawaban
Untuk ini kesalahan itu mengatakan itu mengharapkan array bukan struct. Jadi salah satu cara mudah untuk melakukannya adalah dengan mengiris pointer dan memberikannya ke rawWrite:
stream.rawWrite((&tr)[0 .. 1]);
The (&tr)mendapat alamat, sehingga mengubah struct Anda menjadi pointer. Kemudian [0 .. 1]sarana mendapatkan sepotong dari awal, mengambil hanya satu elemen.
Jadi Anda sekarang memiliki T[]rawWrite yang dapat menangani berisi satu elemen Anda.
Berhati-hatilah jika Anda menggunakan @safeanotasi ini tidak akan lolos, Anda harus menandainya @trusted. Juga tentu saja setiap referensi di dalam struct Anda (termasuk string) akan ditulis sebagai penunjuk biner alih-alih data seperti yang pasti Anda ketahui dari pengalaman C. Tetapi jika Anda menunjukkannya di sana, Anda baik-baik saja.
edit: BTW Anda juga bisa menggunakan fwritejika Anda suka, salin / tempel kode yang sama dari C (kecuali itu foo.sizeofbukan sizeof foo). Hal D Filehanyalah pembungkus kecil di sekitar C FILE*dan Anda bisa mendapatkan FILE * asli kembali untuk diteruskan ke fungsi lain denganstream.getFP() http://dpldocs.info/experimental-docs/std.stdio.File.getFP.html )
rawWrite mengharapkan sebuah array, tetapi ada banyak solusi.
Salah satunya adalah membuat array elemen tunggal.
file.rawWrite([myStruct]);
Yang lainnya adalah mentransmisikan struct ke dalam array. Perpustakaan saya yang disebut bitleveld memiliki fungsi untuk itu yang disebut reinterpretAsArray. Ini juga memudahkan untuk membuat checksum dari struct tersebut.
Sesekali saya mengalami masalah dengan penyelarasan menggunakan metode ini, jadi berhati-hatilah. Bisa diperbaiki dengan mengubah alignproperti struct.