FILETIME до __int64

Как правильно конвертировать FILETIME структурировать в __int64? Подскажите пожалуйста?

7 ответов

Я не думаю, что вы предполагаете: "Не бросайте указатель на FILETIME структура либо ULARGE_INTEGER* или же __int64* значение, потому что это может вызвать ошибки выравнивания в 64-битной Windows."

Источник.

Если бы вы действительно хотели, это было бы что-то вроде:

__int64 to_int64(FILETIME ft)
{
    return static_cast<__int64>(ft.dwHighDateTime) << 32 | ft.dwLowDateTime;
}

FILETIME ft = // ...
__int64 t = to_int64(ft);

Но что-то вроде:

FILETIME ft = // ...
__int64 t = *reinterpet_cast<__int64*>(&ft);

Плохо.

Нет необходимости возвращаться к тайным конструкциям с использованием побитового ИЛИ. Windows API имеет все необходимое для этого.

unsigned __int64    convert( const FILETIME & ac_FileTime )
{
  ULARGE_INTEGER    lv_Large ;

  lv_Large.LowPart  = ac_FileTime.dwLowDateTime   ;
  lv_Large.HighPart = ac_FileTime.dwHighDateTime  ;

  return lv_Large.QuadPart ;
}  

Или, если вы хотите перейти к __int64 напрямую.

__int64 convert_to_int64( const FILETIME & ac_FileTime )
{
  return static_cast< __int64 > ( convert( ac_FileTime ) ) ;
}

Пытаться

(__int64(filetime.dwHighDateTime)<<32) | __int64(filetime.dwLowDateTime)

Конечно, вы можете просто передать __int64, приведенное к времени файла, следующим образом *(FILETIME*)&int64Val. Это будет хорошо работать под Visual C++.

т.е.

__int64 createTime = 0;
__int64 accessTime = 0;
__int64 writeTime = 0;
GetFileTime( hFile, *(FILETIME*)&createTime, *(FILETIME*)&accessTime, *(FILETIME*)&writeTime );

Вы можете попробовать следующий код. код из хромового проекта

template <class Dest, class Source>
inline Dest bit_cast(const Source& source) {
 Dest dest;
 memcpy(&dest, &source, sizeof(dest));
 return dest;
}

//FILETIME to __int64

__int64 FileTimeToMicroseconds(const FILETIME& ft) {
 return bit_cast<__int64, FILETIME>(ft) / 10;
}

void MicrosecondsToFileTime(__int64 us, FILETIME* ft) {
 *ft = bit_cast<FILETIME, __int64>(us * 10);
}

int _tmain(int argc, _TCHAR* argv[])
{
 __int64 nTmpUint64 = 13060762249644841;

 time_t unixtime;
 FILETIME nTmpFileTm;
 MicrosecondsToFileTime(nTmpUint64,&nTmpFileTm);

 return 0;
}

Три способа, которые имеют наилучшую производительность (одна инструкция на ассемблере). Протестировано только в Visual C++ 2022 x64.

      auto u = std::bit_cast<std::uint64_t>(ft)

Лучший путь.

      auto u = *reinterpret_cast<std::uint64_t _UNALIGNED*>(&ft)

Недостаток:_UNALIGNEDмакрос (и__unalignedмодификатор) является нестандартным. Но почти у каждого компилятора есть этот модификатор в той или иной форме.

      memcpy(&u, &ft, sizeof(u))

Недостаток: этот код будет хорошо оптимизирован, только если вы включите опцию компилятора C++ «Enable Intrinsic Functions».

Другие ответы имеют некоторые накладные расходы.

      (static_cast<std::uint64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime

Генерирует побитовые операции.

      ULARGE_INTEGER{ft.dwLowDateTime, ft.dwHighDateTime}.QuadPart

Генерирует две 32-битные операции вместо одной 64-битной.

У меня была точно такая же проблема, я искал ее в Google и пришел сюда. Но я также нашел полезную страницу поддержки Microsoft по адресу
https://support.microsoft.com/en-gb/help/188768/info-working-with-the-filetime-structure

Он говорит:


Выполнение арифметики с указанием времени файла

Часто бывает необходимо выполнить простую арифметику над временем файла. Например, вам может потребоваться узнать, когда файлу 30 дней. Чтобы выполнить арифметические действия с файловым временем, вам необходимо преобразовать FILETIME в четверное слово (64-битное целое число), выполнить арифметические действия, а затем преобразовать результат обратно в FILETIME.

Предполагая, что ft - это структура FILETIME, содержащая время создания файла, следующий пример кода добавляет 30 дней ко времени:

   ULONGLONG qwResult;

   // Copy the time into a quadword.
   qwResult = (((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime;

   // Add 30 days.
   qwResult += 30 * _DAY;

   // Copy the result back into the FILETIME structure.
   ft.dwLowDateTime  = (DWORD) (qwResult & 0xFFFFFFFF );
   ft.dwHighDateTime = (DWORD) (qwResult >> 32 );

Изменить: я понимаю, что это просто подтверждает некоторые другие ответы, но я подумал, что это стоит добавить для разъяснения.

Другие вопросы по тегам