gpt4 book ai didi

c# - 将 DateTime 序列化为二进制

转载 作者:太空狗 更新时间:2023-10-29 20:54:49 26 4
gpt4 key购买 nike

如何正确序列化 DateTime 对象(例如使用 BinaryWriter)并保留其完整状态?

我的印象是日期时间仅由一个内部长整数表示,并且该整数可作为 DateTime 的 Ticks 属性访问。但是,查看实现,Ticks 属性实际上返回存储在名为 dateData

的 ulong 中的真实内部数据的子集

Ticks(仅获取 InternalTicks)是这样实现的:

public long InternalTicks
{
get { return (long) this.dateData & 4611686018427387903L; }
}

据我所知,这意味着 dateData 可能包含 Ticks 属性未显示的信息。

更奇怪的是,DateTime 的 BinaryFormatter 序列化在 GetObjectData() 中执行此操作:

info.AddValue("ticks", this.InternalTicks);
info.AddValue("dateData", this.dateData);

这将在流中输出两个 long,其中一个很容易从另一个恢复!

如何在不丢失任何内部状态的情况下序列化我的 DateTime(当然最好只有 8 个字节,并且没有反射)。我在想也许它可以(不安全)直接转换为 ulong?

或者我无缘无故地担心,Ticks 属性是否真的编码了所有必要的状态?

最佳答案

有两条信息需要担心:

  • 蜱虫
  • DateTimeKind

在内部,它们都被编码成一个 long,像这样的 dateData:

this.dateData = (ulong) (ticks | (((long) kind) << 62));

因此 Ticks 属性将编码所有状态。它将缺少 DateTimeKind 信息。

dateData 确实 对所有数据进行了编码,因此序列化程序同时存储了 Ticks!

所以你可以这样做:

ulong dataToSerialise = (ulong) (date.Ticks | ((long) date.Kind) << 62);

反序列化时,你可以这样做:

long ticks = (long)(deserialisedData & 0x3FFFFFFFFFFFFFFF);
DateTimeKind kind = (DateTimeKind)(deserialisedData >> 62);
DateTime date = new DateTime(ticks, kind);

这确实利用了有关 DateTime 内部结构的知识,理论上它可能会在未来发生变化,这可能会破坏这种序列化。


编辑

本地时间调整有一些问题。

所以我建议您不要乱搞以上所有内容,而是查看 DateTime.ToBinary()DateTime.FromBinary() 允许您序列化为 long 的方法,但要遵守与本地时间调整相关的警告。这些注意事项在上面的 MSDN 链接中有完整记录。

关于c# - 将 DateTime 序列化为二进制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15919598/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com