การเขียนโครงสร้างไบนารีดิบไปยังไฟล์ใน D?
ฉันกำลังพยายามมีไฟล์ไบนารีซึ่งมีบันทึกไบนารีหลายรายการที่กำหนดไว้ในบางstruct
ไฟล์ อย่างไรก็ตามดูเหมือนว่าฉันจะหาวิธีทำไม่ได้ มองไปที่ตัวอย่างอื่น ๆ ผมได้มีการจัดการที่จะเขียนstring
s โดยไม่มีปัญหา struct
แต่ไม่ได้ ผมแค่อยากจะเขียนมันเหมือนฉันจะอยู่ในC
ที่มีfwrite(3)
แต่ในD
รุ่นที่ 2
นี่คือสิ่งที่ฉันได้ลองทำแล้ว:
- การใช้
stream.write(tr)
- เขียนการเป็นตัวแทนที่อ่านได้ / ดีบักของมนุษย์ - ใช้
stream.rawWrite(tr)
- ฟังดูเหมือนสิ่งที่ฉันต้องการ แต่ไม่สามารถรวบรวมด้วย:
ข้อผิดพลาด: template std.stdio.File.rawWrite ไม่สามารถอนุมานฟังก์ชันจากประเภทอาร์กิวเมนต์ได้! () (TitleRecord) ผู้สมัครคือ:
/usr/lib/ldc/x86_64-linux-gnu/include/d/std/stdio.d(1132): std.stdio.File.rawWrite (T) (ใน T [] บัฟเฟอร์)
- พยายาม
rawWrite
ตามข้างต้น แต่การแคสต์ข้อมูลไปยังสิ่งต่างๆยังไม่เคยรวบรวม - แม้จะพยายามกลับไป
C
ด้วยfwrite
แต่ก็ไม่สามารถลงลึกพอที่จะรับไฟล์อธิบายที่ฉันต้องการได้
การอ่านเอกสารไม่ได้มีประโยชน์มากนัก (การเขียนสตริงก็ใช้ได้ผลกับฉันเช่นกัน แต่ไม่ใช่การเขียน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);
}
คำตอบ
สำหรับสิ่งนี้ข้อผิดพลาดที่บอกว่าคาดว่าอาร์เรย์ไม่ใช่โครงสร้าง วิธีง่ายๆวิธีหนึ่งในการทำก็คือเพียงแค่แบ่งตัวชี้และส่งให้กับ rawWrite:
stream.rawWrite((&tr)[0 .. 1]);
(&tr)
ได้รับที่อยู่จึงแปลง struct ของคุณเพื่อชี้ จากนั้น[0 .. 1]
วิธีการรับชิ้นส่วนของมันจากจุดเริ่มต้นคว้าเพียงองค์ประกอบเดียว
ดังนั้นตอนนี้คุณมีT[]
rawWrite ที่สามารถจัดการกับองค์ประกอบหนึ่งของคุณได้
ได้รับการเตือนถ้าคุณใช้คำอธิบายประกอบนี้จะไม่ผ่านคุณจะต้องทำเครื่องหมาย@safe
@trusted
นอกจากนี้การอ้างอิงใด ๆ ในโครงสร้างของคุณ (รวมถึงstring
) จะถูกเขียนเป็นตัวชี้ไบนารีแทนข้อมูลตามที่คุณทราบจากประสบการณ์ C แต่ในกรณีที่คุณแสดงให้เห็นว่าคุณสบายดี
แก้ไข: BTW คุณสามารถใช้fwrite
หากต้องการคัดลอก / วางรหัสเดียวกันทับจาก C (ยกเว้นจะfoo.sizeof
ใช้แทนsizeof foo
) File
สิ่งD เป็นเพียงกระดาษห่อเล็ก ๆ รอบ ๆ C FILE*
และคุณจะได้รับ FILE เดิม * กลับออกมาเพื่อส่งต่อไปยังฟังก์ชันอื่น ๆ ด้วยstream.getFP()
http://dpldocs.info/experimental-docs/std.stdio.File.getFP.html )
rawWrite
คาดว่าจะมีอาร์เรย์ แต่มีวิธีแก้ปัญหามากมาย
หนึ่งคือการสร้างอาร์เรย์องค์ประกอบเดียว
file.rawWrite([myStruct]);
อีกอันหนึ่งกำลังหล่อโครงสร้างเป็นอาร์เรย์ ไลบรารีของฉันชื่อ bitleveld มีฟังก์ชันสำหรับการเรียกreinterpretAsArray
นั้น นอกจากนี้ยังทำให้ง่ายต่อการสร้างเช็คซัมของโครงสร้างดังกล่าว
นาน ๆ ครั้งฉันพบปัญหาเกี่ยวกับการจัดตำแหน่งโดยใช้วิธีนี้ดังนั้นโปรดใช้ความระมัดระวัง สามารถแก้ไขได้โดยการเปลี่ยนalign
คุณสมบัติของโครงสร้าง