如何在D语言2.x版本中将结构体写入二进制文件?
在D语言2.x中实现类似C语言fwrite的结构体二进制写入方法
我懂你这种挠头的感觉——想在D语言里直接把结构体像C的fwrite那样怼进二进制文件,试了好几种方法要么输出成可读文本,要么编译报错,明明感觉应该有简单办法就是找不到。别着急,咱们来把这个问题捋清楚,给你几个靠谱的解决方案。
为啥你之前的尝试失败了?
先拆解下你遇到的问题:
stream.write(tr):这个方法本来就是用来输出人类可读的调试信息的,不是写二进制,所以肯定不符合需求。stream.rawWrite(tr):rawWrite的参数要求是数组/切片类型,你传单个结构体的话,模板没法推导类型,自然编译报错。- 强制转
ubyte[52]失败:你的TitleRecord大小是2(short)+49(char数组)=51字节,硬转成52字节的数组,类型大小不匹配,编译器当然不干。 - 直接转
ubyte[]:结构体不是数组,编译器不知道这个切片的长度,所以也没法通过。
正确的实现方法
这里有两种简单直接的方式,都能实现类似Cfwrite的效果:
方法1:把结构体转成单个元素的切片传给rawWrite
D里可以通过指针取单个元素的切片,这样rawWrite就能直接识别并写入二进制内容了:
import std.stdio; struct TitleRecord { short id; char[49] text; } void main() { TitleRecord tr; auto stream = File("filename.dat","wb+"); tr.id = 1234; tr.text = "hello world"; // 核心:把单个结构体转成长度为1的切片 stream.rawWrite((&tr)[0..1]); stream.close(); }
(&tr)[0..1]会把结构体指针转换成一个包含单个元素的TitleRecord[]切片,rawWrite会直接把这个切片对应的内存字节原封不动写入文件,完全符合你要的效果。
方法2:用std.bitmanip.toBytes转成字节数组(更简洁)
D标准库的std.bitmanip模块提供了toBytes函数,可以自动把结构体转换成ubyte[]字节数组,然后直接用rawWrite写入,代码更清爽:
import std.stdio; import std.bitmanip; struct TitleRecord { short id; char[49] text; } void main() { TitleRecord tr; auto stream = File("filename.dat","wb+"); tr.id = 1234; tr.text = "hello world"; // 自动转成字节数组 ubyte[] structBytes = tr.toBytes(); stream.rawWrite(structBytes); stream.close(); }
额外提示:字节序兼容性
如果你的二进制文件需要和C或者其他平台交互,要注意字节序问题。D默认用主机字节序,如果需要固定大端/小端,可以给结构体加注解:
import std.bitmanip; // 按小端序存储,和x86平台的C程序一致 @littleEndian struct TitleRecord { short id; char[49] text; }
这样toBytes会按照指定的字节序转换内容,确保跨平台读写不会出问题。
内容的提问来源于stack exchange,提问作者Matija Nalis




