C++17:跨Win/Linux如何将std::filesystem::file_time_type存为整数?
跨平台文件时间转整数的C++17实现方案
背景
开发一款跨Windows和Linux的程序,需收集目录文件的时间并以数字形式存入文本文件;后续程序读取这些文件,将存储的数字与新获取的时间数值对比,且读写程序可能运行在不同平台,文件来自共享网络驱动器。
核心问题
如何在C++17中以最优且可移植的方式,将std::filesystem::last_write_time()返回的时间输出为单个整数?
要求
- 基于
std::filesystem::file_time_type - 兼容C++17标准
- 跨平台可移植
- 输出为单个整数
注:本问题非重复提问!
已尝试的方案(存在缺陷)
以下两种方案通过时间点转换实现,但两次调用now()会导致结果抖动:
template < typename TP > std::time_t to_time_tnew( TP tp ) { using namespace std::chrono; auto sctp = time_point_cast< system_clock::duration >( tp - TP::clock::now() + system_clock::now() ); return system_clock::to_time_t( tp ); }
template < typename TP > std::time_t to_time_t( TP tp ) { // using namespace std::chrono; auto sctp = std::chrono::time_point_cast< std::chrono::system_clock::duration >( tp - TP::clock::now() + std::chrono::system_clock::now() ); return std::chrono::system_clock::to_time_t( sctp ); }
当前临时适配方案(Windows + 树莓派Linux)
虽依赖平台宏和常量仅作为原型实现,代码如下:
#include <cstdarg> #include <inttypes.h> #include <filesystem> #include <chrono> #include <fstream> #include <sstream> #include <iostream> #include <iomanip> #ifdef WIN32 #define FILE_TIME__FILE_TIME_OFFSET ( std::filesystem::__std_fs_file_time_epoch_adjustment ) // "( 116444736000000000ull )" #define FILE_TIME__FILE_TIME_GAIN ( 10000000ull ) #else #define FILE_TIME__FILE_TIME_OFFSET ( 12009080074ull ) #define FILE_TIME__FILE_TIME_GAIN ( 1000000000ull ) #endif #ifdef WIN32 std::time_t TimeHelper::to_time_t( const std::filesystem::file_time_type file_time ) const { std::time_t rv = 0ull; const std::filesystem::file_time_type *ptr = &file_time; uint64_t * timeptr = ( uint64_t * ) ptr; uint64_t time = *timeptr; if ( time >= FILE_TIME__FILE_TIME_OFFSET ) { time -= FILE_TIME__FILE_TIME_OFFSET; time += ( FILE_TIME__FILE_TIME_GAIN >> 1 ); // do correct rounding by adding halv of dividend before division time /= FILE_TIME__FILE_TIME_GAIN; rv = time; } return rv; } std::filesystem::file_time_type TimeHelper::to_FileTimeType( const std::time_t time ) const { uint64_t time_t1 = time * FILE_TIME__FILE_TIME_GAIN; // time_t to 100ns uint64_t time_t2 = time_t1 + FILE_TIME__FILE_TIME_OFFSET; // time_t to offset 01.01.1601 std::filesystem::file_time_type *ptr = ( std::filesystem::file_time_type * ) &time_t2; std::filesystem::file_time_type rv = *ptr; return rv; } #else std::time_t TimeHelper::to_time_t( const std::filesystem::file_time_type file_time ) const { const std::filesystem::file_time_type *ftptr = &file_time; const uint64_t ft = *( ( uint64_t * ) ftptr ); const uint64_t offs = FILE_TIME__FILE_TIME_OFFSET; const uint64_t ts = ft / FILE_TIME__FILE_TIME_GAIN; std::time_t rv = 0; if ( offs < ts ) { rv = ( std::time_t ) ( ts - offs ); } return rv; } std::filesystem::file_time_type TimeHelper::to_FileTimeType( const std::time_t time ) const { uint64_t offs = FILE_TIME__FILE_TIME_OFFSET; uint64_t t1 = time + offs; uint64_t t2 = t1 * FILE_TIME__FILE_TIME_GAIN; std::filesystem::file_time_type ft = *( ( std::filesystem::file_time_type * ) &t2 ); return ft; } #endif
内容的提问来源于stack exchange,提问作者Jesko
相关产品推荐
相关产品推荐

