保存并加载std::chrono::time_point到文件

Saving and loading std::chrono::time_point to file

本文关键字:point 文件 time chrono 加载 std 保存      更新时间:2023-10-16

我试图简单地将当前时间保存并重新加载到文件中。例如:

std::ifstream ifs(solar_system_cache_file,
        std::ios::in | std::ios::binary);
if (!ifs.is_open()) {
    return false;
}
std::chrono::system_clock::time_point cache_valid_time;
ifs >> cache_valid_time;
if (std::chrono::system_clock::now() < cache_valid_time) {
    std::cout << "Cache is VALID." << std::endl;
}
ifs.close();
return true;

std::ofstream ofs(solar_system_cache_file,
        std::ios::out | std::ios::binary);
if (!ofs.is_open())
    return;
ofs << std::chrono::system_clock::now() + 12h;
ofs.close();

这类事情并不复杂,但我已经四处寻找了几个小时,却找不到相关信息。有一些关于如何使用duration_cast<long, std::milli>进行强制转换的示例,但std::chrono非常复杂,很难导航(和消化)。

简而言之,我认为我需要将当前时间转换为long(或类似的大型类型)并保存它。当反序列化时间时,我只需要将其强制转换回time_point。这听起来很简单,但我做不到

最后,在fstream中简单地管道化时间会产生常见的invalid operands to binary expression错误。

如有任何帮助,或链接到好的教程/指南,我们将不胜感激。感谢

如果您想要二进制序列化,请不要使用格式化的文本例程来实现序列化。:-]

时钟的time_point只是一个算术类型的包装,该算术类型是自时钟的历元以来经过的某个时间单位的周期数。您真正需要做的就是以二进制形式序列化算术值:

保存

using namespace std::chrono_literals;
using clock_t = std::chrono::system_clock;
std::ofstream ofs{ solar_system_cache_file, std::ios::binary };
if (!ofs.is_open()) {
    return;
}
auto const cache_time = (clock_t::now() + 12h).time_since_epoch().count();
ofs.write(reinterpret_cast<char const*>(&cache_time), sizeof cache_time);
ofs.close();

加载

std::ifstream ifs{ solar_system_cache_file, std::ios::binary };
if (!ifs.is_open()) {
    return false;
}
clock_t::rep file_time_rep;
if (!ifs.read(reinterpret_cast<char*>(&file_time_rep), sizeof file_time_rep)) {
    return false;
}
ifs.close();
clock_t::time_point const cache_valid_time{ clock_t::duration{ file_time_rep } };
std::time_t const file_time{ clock_t::to_time_t(cache_valid_time) };
std::cout << std::ctime(&file_time);

注意,将openmode::in传递到输入流并且将openmode::out传递到输出流是冗余的。

同样重要的是,请注意二进制序列化是不可移植的:

  1. std::chrono::system_clock::rep的类型是由实现定义的——唯一的要求是它是一个有符号的算术类型——因此可以从一个编译器/stdlib/build-config更改为下一个
  2. 即使您通过std::chrono::duration_cast控制表示类型,积分类型的端序和浮点类型的表示作为一个整体也是特定于体系结构的

因此,只能使用与序列化代码使用相同体系结构/编译器/stdlib/config构建的代码来反序列化数据。

好吧,经过一番折腾,我终于拿到了。

答案是std::time_t,它是朋友std::chrono::system_clock::from_time_tstd::chrono::system_clock::to_time_t

因此,要保存,您所要做的就是将::now()转换为time_t,并将其通过管道传输到文件中。要加载,请使用from_time_t执行相反的操作。

保存

std::ofstream ofs(solar_system_cache_file,
        std::ios::out | std::ios::binary);
if (!ofs.is_open())
    return;
auto cache_time = std::chrono::system_clock::now() + 12h;
ofs << std::chrono::system_clock::to_time_t(cache_time);
ofs.close();

加载

std::ifstream ifs(solar_system_cache_file,
        std::ios::in | std::ios::binary);
if (!ifs.is_open()) {
    return false;
}
std::time_t file_time;
ifs >> file_time;
std::cout << std::ctime(&file_time);
auto cache_valid_time = std::chrono::system_clock::from_time_t(file_time);
ifs.close();

很简单,干杯!