将原始二进制结构写入 D 中的文件?
Writing a raw binary structure to file in D?
我正在尝试创建一个二进制文件,其中包含一些 struct
中定义的多个二进制记录。但是,我似乎无法找到如何去做。查看其他示例,我成功地编写了 string
s,但没有问题 struct
。我只想像在 C
和 fwrite(3)
中那样写它,但是在 D
版本 2.
中
这是我到目前为止尝试过的方法:
- 使用
stream.write(tr)
- 写入人类 readable/debug 表示
- 使用
stream.rawWrite(tr)
- 这听起来像我需要的,但无法编译:
Error: template std.stdio.File.rawWrite cannot deduce function from
argument types !()(TitleRecord), candidates are:
/usr/lib/ldc/x86_64-linux-gnu/include/d/std/stdio.d(1132): std.stdio.File.rawWrite(T)(in T[] buffer)
- 像上面那样尝试
rawWrite
,但是将数据转换为各种东西,也永远不会编译。
- 甚至试图用
fwrite
回到 C
,但无法深入到我需要的文件描述符。
阅读the docs has not been very helpful (writing strings works for me too, but not writing struct
). I'm sure there must be simple way to do it, but I'm not able to find it.... Other SO questions did not help me。我 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)
获取地址,从而将您的结构转换为指针。然后 [0 .. 1]
表示从头开始获取一部分,只抓取一个元素。
因此你现在有一个 T[]
rawWrite 可以处理包含你的一个元素。
请注意,如果您使用 @safe
注释,这将不会通过,您必须将其标记为 @trusted
。当然,你的结构中的任何引用(包括 string
)都将被写为二进制指针而不是数据,正如你从 C 经验中肯定知道的那样。但是如果你在那里展示了你就没事了。
编辑:顺便说一句,如果你愿意,你也可以只使用 fwrite
,copy/pasting 来自 C 的相同代码(除了它是 foo.sizeof
而不是 sizeof foo
) . D File
只是 C 的 FILE*
的一个小包装,您可以使用 stream.getFP()
http://dpldocs.info/experimental-docs/std.stdio.File.getFP.html )
rawWrite
需要一个数组,但有很多解决方法。
一种是创建单元素数组。
file.rawWrite([myStruct]);
另一个正在将结构转换为数组。我的名为 bitleveld 的库有一个名为 reinterpretAsArray
的函数。这也使得创建所述结构的校验和变得容易。
我偶尔会遇到使用这种方法对齐的问题,所以要小心。可以通过更改结构的 align
属性 来修复。
我正在尝试创建一个二进制文件,其中包含一些 struct
中定义的多个二进制记录。但是,我似乎无法找到如何去做。查看其他示例,我成功地编写了 string
s,但没有问题 struct
。我只想像在 C
和 fwrite(3)
中那样写它,但是在 D
版本 2.
这是我到目前为止尝试过的方法:
- 使用
stream.write(tr)
- 写入人类 readable/debug 表示 - 使用
stream.rawWrite(tr)
- 这听起来像我需要的,但无法编译:
Error: template std.stdio.File.rawWrite cannot deduce function from argument types !()(TitleRecord), candidates are:
/usr/lib/ldc/x86_64-linux-gnu/include/d/std/stdio.d(1132): std.stdio.File.rawWrite(T)(in T[] buffer)
- 像上面那样尝试
rawWrite
,但是将数据转换为各种东西,也永远不会编译。 - 甚至试图用
fwrite
回到C
,但无法深入到我需要的文件描述符。
阅读the docs has not been very helpful (writing strings works for me too, but not writing struct
). I'm sure there must be simple way to do it, but I'm not able to find it.... Other SO questions did not help me。我 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)
获取地址,从而将您的结构转换为指针。然后 [0 .. 1]
表示从头开始获取一部分,只抓取一个元素。
因此你现在有一个 T[]
rawWrite 可以处理包含你的一个元素。
请注意,如果您使用 @safe
注释,这将不会通过,您必须将其标记为 @trusted
。当然,你的结构中的任何引用(包括 string
)都将被写为二进制指针而不是数据,正如你从 C 经验中肯定知道的那样。但是如果你在那里展示了你就没事了。
编辑:顺便说一句,如果你愿意,你也可以只使用 fwrite
,copy/pasting 来自 C 的相同代码(除了它是 foo.sizeof
而不是 sizeof foo
) . D File
只是 C 的 FILE*
的一个小包装,您可以使用 stream.getFP()
http://dpldocs.info/experimental-docs/std.stdio.File.getFP.html )
rawWrite
需要一个数组,但有很多解决方法。
一种是创建单元素数组。
file.rawWrite([myStruct]);
另一个正在将结构转换为数组。我的名为 bitleveld 的库有一个名为 reinterpretAsArray
的函数。这也使得创建所述结构的校验和变得容易。
我偶尔会遇到使用这种方法对齐的问题,所以要小心。可以通过更改结构的 align
属性 来修复。