怎样在 LUA 中将 DWORD 转换成 FILETIME?

我正在尝试读取一个包含两个 DWORD 类型数据的文件,这个文件的类型是 FILETIME(这是一个预读文件)。

我在文件偏移量为 0x81(由于 Lua 的索引是从 1 开始的,所以需要加上 1)处进行读取。我该如何将这 8 个字节转换为文件时间戳,并仅使用 Lua 完成?

在十六进制编辑器中,从 0x80 开始,我有:

FB54B341B70CCf01

需要将其转换为 2014年1月8日 的文件时间戳。

点赞
用户68204
用户68204

什么是FILETIME

Windows平台 定义 FILETIME 为64位整数,“从1601年1月1日UTC起每100纳秒一个计数的总数”。

你在使用 Lua 处理 FILETIME 时至少会遇到两个挑战。

首先,一个 FILETIME 是一个64位整数,而 Lua 内部存储数字使用IEEE双精度,只支持56位精度。根据我刚刚草绘的信封的精度,你需要超过57个有效位来命名今天的任何时间作为 FILETIME

(顺便说一句:我估计了一下,发现一年里大约有1e7*pi秒钟,在一秒钟内有1e7个100纳秒的滴答声,今天距离 FILETIME时期大约413年。因此2014年的日期大约需要log2(413e14* pi)位,或者略大于57位。)

其次,纯Lua没有易于使用的函数将二进制数据结构转换为本地Lua数据类型。虽然使用 string.byte()string.sub() 来构建这样的函数并且安全性良好,但是这是你必须自己构建的,或者从第三方来源找到。

但是要注意,尽管有二进制结构库,但由于Lua数字的限制,其中许多只提供对64位整数的有限支持。您可能最好使用 C 编写的手工制作的模块,该模块将 FILETIME 存储在 userdata 中,并提供适当的运算符以允许它们进行比较、转换为和从字符串中转换等操作。

你的例子

从我的十六进制编辑器的0x80开始,我有:

FB54B341B70CCf01

需要对应到01/08/2014

PC上的Windows是一个小端平台。这意味着值存储在具有最低地址的最不重要的字节。因此,我们可以通过反转字节来使您的样本时间戳更加可读:

01CF0CB741B354FB

正如预期的那样,第57位是最重要的设置位,因此这个值是这个世纪的合理值。

2014-01-16 01:54:14