保存和加载 std::chrono::time_point 到文件
Saving and loading std::chrono::time_point to file
我正在尝试简单地保存并重新加载文件中的当前时间。例如:
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
错误。
感谢任何帮助,或指向好的 tutorials/guides 的链接。
谢谢
好吧,经过一番折腾,我终于明白了。
答案是std::time_t
,是朋友std::chrono::system_clock::from_time_t
和std::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();
毕竟很简单,干杯!
如果您想要二进制序列化,请不要使用格式化文本例程来实现您的序列化。 :-]
时钟的 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
传递给输出流是多余的。
此外,重要的是,请注意二进制序列化不可移植:
std::chrono::system_clock::rep
的类型是实现定义的——唯一的要求是它是有符号算术类型——因此可以从一个 compiler/stdlib/build 配置更改为下一个。
- 即使您通过
std::chrono::duration_cast
控制表示类型,整数类型的字节顺序和浮点类型的表示作为一个整体也是特定于体系结构的。
因此,您只能依靠使用与序列化代码相同的 architecture/compiler/stdlib/config 构建的代码来反序列化数据。
我正在尝试简单地保存并重新加载文件中的当前时间。例如:
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
错误。
感谢任何帮助,或指向好的 tutorials/guides 的链接。 谢谢
好吧,经过一番折腾,我终于明白了。
答案是std::time_t
,是朋友std::chrono::system_clock::from_time_t
和std::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();
毕竟很简单,干杯!
如果您想要二进制序列化,请不要使用格式化文本例程来实现您的序列化。 :-]
时钟的 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
传递给输出流是多余的。
此外,重要的是,请注意二进制序列化不可移植:
std::chrono::system_clock::rep
的类型是实现定义的——唯一的要求是它是有符号算术类型——因此可以从一个 compiler/stdlib/build 配置更改为下一个。- 即使您通过
std::chrono::duration_cast
控制表示类型,整数类型的字节顺序和浮点类型的表示作为一个整体也是特定于体系结构的。
因此,您只能依靠使用与序列化代码相同的 architecture/compiler/stdlib/config 构建的代码来反序列化数据。