You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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

火山引擎 最新活动