14

当使用以下方法进行转换时,我阅读的大多数文件都得到了正确的时间:

// works great most of the time
private static DateTime convertToDateTime(System.Runtime.InteropServices.ComTypes.FILETIME time)
{
    long highBits = time.dwHighDateTime;
    highBits = highBits << 32;
    return DateTime.FromFileTimeUtc(highBits + time.dwLowDateTime);
}

在这里,我在 Visual Studio 中有一个示例来说明此方法有时如何不起作用,例如,我将显示计算机中的实际文件和调试。所以恰好在我的调试中的文件是:

“A:\Users\Tono\Documents\Visual Studio 2010\Projects\WpfApplication4\WpfApplication4\obj\x86\Debug\App.g.cs” 在此处输入图像描述

这是我试图转换为 DateTime 的 FILETIME “顺便说一下,我需要 LastWriteTime”

在此处输入图像描述

在这里,您可以从该文件中看到 dwHighDateTime = 30136437 和 dwLowDateTime = -2138979250。

当我运行我的方法和其他技术时,我得到以下日期: 在此处输入图像描述

到目前为止,一切似乎都运行良好。但是为什么当我在 Windows 中浏览并查找该特定文件时我得到不同的日期!?这是我看到文件属性时得到的日期: 在此处输入图像描述

为什么日期不匹配?我究竟做错了什么?

4

5 回答 5

19

您需要按位组合 LS 和 MS 值,而不是算术。

尝试:

        ulong high = 30136437;
        unchecked
        {
            int low = -2138979250;
            uint uLow = (uint)low;
            high = high << 32;
            Date dt = DateTime.FromFileTime((long) (high | (ulong)uLow));
        }

或者以下任何一项也应该起作用:

long highBits = time.dwHighDateTime;     
highBits = highBits << 32;     

return DateTime.FromFileTimeUtc(highBits + (long) (uint) time.dwLowDateTime); 

return DateTime.FromFileTimeUtc(highBits | (long) (uint) time.dwLowDateTime); 

return DateTime.FromFileTimeUtc(highBits + ((long)low & 0xFFFFFFFF))

return DateTime.FromFileTimeUtc(highBits | ((long)low & 0xFFFFFFFF))

您可以通过添加而不是按位来逃脱,或者如果您确定这些值是正数(并且没有共同的位)。但是按位或更好地表达了意图。

于 2011-05-21T19:03:57.407 回答
9

我参加聚会有点晚了,但这对我来说确实有效:

public static class FILETIMEExtensions
{
    public static DateTime ToDateTime(this System.Runtime.InteropServices.ComTypes.FILETIME time)
    {
        ulong high = (ulong)time.dwHighDateTime;
        uint low = (uint)time.dwLowDateTime;
        long fileTime = (long)((high << 32) + low);
        try
        {
            return DateTime.FromFileTimeUtc(fileTime);
        }
        catch
        {
            return DateTime.FromFileTimeUtc(0xFFFFFFFF);
        }
    }
}

注意:不要相信 Windows 资源管理器。例如,使用File.GetLastWriteTimeUtc方法来验证文件系统实际具有的内容与此扩展方法返回的内容。资源管理器中有一些错误,在某些情况下不会更新文件时间。干杯! :)

注意:要对此进行测试,您需要使用最大值。所以,假设dwHighDateTime = dwLowDateTime = UInt32.MaxValue = 4294967295 = 0xFFFFFFFF,它遵循(long)(((ulong)UInt32.MaxValue << 32) + UInt32.MaxValue) = -1 = 0xFFFFFFFFFFFFFFFF。不幸的是,Windows API 中的谬误似乎是最终需要将时间转换为一个long值,以便将其用于任何有用的应用程序(因为大多数 Windows API 方法将文件时间作为一个long值),这意味着一次前导位为高 ( 1) 时dwHighDateTime,值变为负数。让我们尝试不高的最长时间。假设dwHighDateTime = Int32.MaxValue = 2147483647 = 0x7FFFFFFFdwLowDateTime = UInt32.MaxValue = 4294967295 = 0xFFFFFFFF,则遵循(long)(((ulong)Int32.MaxValue << 32) + UInt32.MaxValue) = 0x7FFFFFFFFFFFFFFF

注意:0x7FFFFFFFFFFFFFFF已经比 大得多DateTime.MaxValue.ToFileTimeUtc() = 2650467743999999999 = 0x24C85A5ED1C04000,渲染数字对于 .NET 中的任何实际应用程序已经无用。

于 2015-05-19T01:08:01.700 回答
5

这是我见过的另一种将 FileTime 结构转换为 long(使用结构中的编码运算符)的方法,然后可以使用 DateTime.FromFileTime 函数轻松地将其转换为 DateTime:

public struct FileTime
{
    public uint dwLowDateTime;
    public uint dwHighDateTime;

    public static implicit operator long(FileTime fileTime)
    {
        long returnedLong;
        // Convert 4 high-order bytes to a byte array
        byte[] highBytes = BitConverter.GetBytes(fileTime.dwHighDateTime);
        // Resize the array to 8 bytes (for a Long)
        Array.Resize(ref highBytes, 8);

        // Assign high-order bytes to first 4 bytes of Long
        returnedLong = BitConverter.ToInt64(highBytes, 0);
        // Shift high-order bytes into position
        returnedLong = returnedLong << 32;
        // Or with low-order bytes
        returnedLong = returnedLong | fileTime.dwLowDateTime;
        // Return long 
        return returnedLong;
    }
}
于 2012-06-19T22:32:56.770 回答
0

我尝试了以下方法,但没有一个能让我得到正确的时间:
在此处输入图像描述

我从这里得到了方法

于 2011-05-21T19:46:00.003 回答
0

dwLowDateTimedwHighDateTime应该是,uint看起来他们是int。更改此设置很可能会解决它,尽管@Joe 指出您仍应使用|而不是+.

于 2011-05-21T19:23:48.317 回答