การเขียนโครงสร้างไบนารีดิบไปยังไฟล์ใน D?

Aug 19 2020

ฉันกำลังพยายามมีไฟล์ไบนารีซึ่งมีบันทึกไบนารีหลายรายการที่กำหนดไว้ในบางstructไฟล์ อย่างไรก็ตามดูเหมือนว่าฉันจะหาวิธีทำไม่ได้ มองไปที่ตัวอย่างอื่น ๆ ผมได้มีการจัดการที่จะเขียนstrings โดยไม่มีปัญหา 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);
}

คำตอบ

2 AdamD.Ruppe Aug 19 2020 at 21:40

สำหรับสิ่งนี้ข้อผิดพลาดที่บอกว่าคาดว่าอาร์เรย์ไม่ใช่โครงสร้าง วิธีง่ายๆวิธีหนึ่งในการทำก็คือเพียงแค่แบ่งตัวชี้และส่งให้กับ 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 )

1 LászlóSzerémi Aug 19 2020 at 23:55

rawWrite คาดว่าจะมีอาร์เรย์ แต่มีวิธีแก้ปัญหามากมาย

หนึ่งคือการสร้างอาร์เรย์องค์ประกอบเดียว

file.rawWrite([myStruct]);

อีกอันหนึ่งกำลังหล่อโครงสร้างเป็นอาร์เรย์ ไลบรารีของฉันชื่อ bitleveld มีฟังก์ชันสำหรับการเรียกreinterpretAsArrayนั้น นอกจากนี้ยังทำให้ง่ายต่อการสร้างเช็คซัมของโครงสร้างดังกล่าว

นาน ๆ ครั้งฉันพบปัญหาเกี่ยวกับการจัดตำแหน่งโดยใช้วิธีนี้ดังนั้นโปรดใช้ความระมัดระวัง สามารถแก้ไขได้โดยการเปลี่ยนalignคุณสมบัติของโครงสร้าง