.NET big-endian или little-endian?
От: Shadedsun  
Дата: 24.06.08 14:54
Оценка:
В WinAPI есть такие функции как FindFirstFile и FindNextFile, которые используют структуру WIN32_FIND_DATA, для .NET, Микрософт определяет её в виде класса:
[Serializable, StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto), BestFitMapping(false)]
internal class WIN32_FIND_DATA
{
    internal int dwFileAttributes;
    internal int ftCreationTime_dwLowDateTime;
    internal int ftCreationTime_dwHighDateTime;
    internal int ftLastAccessTime_dwLowDateTime;
    internal int ftLastAccessTime_dwHighDateTime;
    internal int ftLastWriteTime_dwLowDateTime;
    internal int ftLastWriteTime_dwHighDateTime;
    internal int nFileSizeHigh;
    internal int nFileSizeLow;
    internal int dwReserved0;
    internal int dwReserved1;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)]
    internal string cFileName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=14)]
    internal string cAlternateFileName;
    public WIN32_FIND_DATA();
}

Я его чуть переделал, и расчета того что ftCreationTime_dwLowDateTime и ftCreationTime_dwHighDateTime располагаются как раз в таком порядке, что если их накрыть long-полем, то оно получит валидное значение:
[Serializable]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
[BestFitMapping(false)]
class WIN32_FIND_DATA
{
    public int dwFileAttributes;
    //public int ftCreationTime_dwLowDateTime;
    //public int ftCreationTime_dwHighDateTime;
    public long CreationTime;
    public int ftLastAccessTime_dwLowDateTime;
    public int ftLastAccessTime_dwHighDateTime;
    public int ftLastWriteTime_dwLowDateTime;
    public int ftLastWriteTime_dwHighDateTime;
    public int nFileSizeHigh;
    public int nFileSizeLow;
           int Reserved0;
           int Reserved1;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public string FileName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
    public string AlternateFileName;
}

но не тут то было, DateTime.FromFileTime() вылетает с руганью на неверное значение параметра. Тогда я поменял в long-поле первое слово и второе местами:
fileData.CreationTime = (long)(((ulong)fileData.CreationTime >> 32) | ((ulong)fileData.CreationTime << 32));

и, о чудо, оно зароботало. Но появилась другая проблема. FileName сдвинулось на одно слово (4 байта) так, как будто я добавил лишнее intовое поле (пример: fileData.FileName вместо "Yahoo!" теперь содержит "hoo!").
Вопрос не жизненно важный, я проблему решил оставив структуру в прежнем виде
public static DateTime FileTimeToDateTime(int highWord, int lowWord)
{
    return DateTime.FromFileTime((((long)highWord) << 32) + lowWord);
}

Интересно почему при замене двух Int32 на одно Int64 поля сдвинулись, и почему Int64 ведет себя так, как будто слова в нем располагаются в big-endian порядке т.е. сначала старшее слово потом младшее, а не так как принято на x86 платформе?
.net big-endian little-endian
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.