2016-05-01 24 views
1

ファイルに現在の時刻を保存してリロードするだけです。たとえば:std :: chrono :: time_pointを保存してファイルに保存する

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が返されます。

助けてください、または良いチュートリアル/ガイドへのリンクです。 ありがとうございました

+0

シリアル化された形式を人間が読めるようにしますか? – ildjarn

+0

いいえ、バイナリ形式です。私は答えとして私の解決策を投稿しました。もちろん、問題でジャブをとることを自由に感じてください:) – scx

答えて

3

バイナリシリアル化が必要な場合は、書式付きテキストルーチンを使用してシリアル化を実装しないでください。 : - ]

クロックのtime_pointは、クロックのエポックから経過した時間単位のピリオドの数である算術型のラッパーです。あなたが本当にやらなければならないことは、そのバイナリ形式でその算術値をシリアル化です:

保存

using namespace std::chrono_literals; 

std::ofstream ofs(solar_system_cache_file, std::ios::binary); 
if (!ofs.is_open()) { 
    return; 
} 

auto const cache_time = (std::chrono::system_clock::now() + 12h).time_since_epoch().count(); 
ofs.write(reinterpret_cast<char const*>(&cache_time), sizeof cache_time); 
ofs.close(); 

ロード

using clk_t = std::chrono::system_clock; 

std::ifstream ifs(solar_system_cache_file, std::ios::binary); 
if (!ifs.is_open()) { 
    return false; 
} 

clk_t::rep file_time_rep; 
if (!ifs.read(reinterpret_cast<char*>(&file_time_rep), sizeof file_time_rep)) { 
    return false; 
} 
ifs.close(); 

clk_t::time_point const cache_valid_time{clk_t::duration{file_time_rep}}; 
std::time_t const file_time = clk_t::to_time_t(cache_valid_time); 
std::cout << std::ctime(&file_time); 

注入力ストリームにopenmode::inを渡すこととopenmode::out出力ストリームへの転送は冗長です。 - 唯一の要件は、それが署名された算術型であることである - ので、コンパイラから変更でき

  1. std::chrono::system_clock::repのタイプは実装定義である:

    また、重要なことは、バイナリシリアライゼーションはポータブルでないことに注意してください/ stdlib/configを次のものに変更します。

  2. 表現タイプをstd::chrono::duration_castで制御した場合でも、整数型のエンディアンと浮動小数点型の表現はアーキテクチャ固有です。

したがって、あなただけのシリアル化コードと同じアーキテクチャ/コンパイラ/ STDLIB /設定で構築されたコードとデータをデシリアライズに頼ることができます。

+0

さらに、エポックは実行ごとに変わることがあります(実際にはsystem_clockでは保証されません)。 –

+0

偉大な答えは、ありがとう。私は 'rep'についてかなり混乱しています、それは何を表現すると思われますか? – scx

+0

@Socapex: 'rep'は、エポックから経過した時間単位の数を保持するために使用される型です。私のシステムでは、 'system_clock :: period'は' std :: nano'であり、 'system_clock :: rep'は' long long'です。したがって、直列化された値は、エポックから経過したナノ秒数を含む 'long long'です。 – ildjarn

1

まあまあまあもうちょっとしばらくしてから私はついにそれを手に入れました。

答えは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(); 

非常に簡単、歓声!

+1

'time_t'(テキスト形式)の精度に満足すればOKです。通常は秒です。 ildjarnの答えは、あなたの 'system_clock'がどのような単位(あなたの場合はナノ秒)を測定しているかに正確であり、よりコンパクトなバイナリ形式を使います。 –