動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)
処理
- 装置などからデータが適宜追加される
- 例: 1000msecごとに1個ずつ
- データを適当な個数で取出しファイルに書出す
- 例: 5秒ごとに5個ずつ
- ファイル名はN分ごとに変更する
関連
- 【C#】現在時刻から直後のきりの良い時刻(5分、10分、15分・・・)を取得する。
- c++ builder > TDateTime > 指定時刻に近い時刻を得る (10分区切り)
- C++ Builder > Form1:項目追加 + Form2:追加項目の取出し > TStringList実装
code v0.1
LoggerUnit.h
//---------------------------------------------------------------------------
#ifndef LoggerUnitH
#define LoggerUnitH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
/*
ログファイルを出力する。
ファイル名はN分ごとに切替わる。
*/
class TFormLogger : public TForm
{
__published: // IDE で管理されるコンポーネント
TTimer *TimerProcess;
void __fastcall TimerProcessTimer(TObject *Sender);
private: // ユーザー宣言
TStringList *m_SL_log; // ログ保存用
// 外部からの受取り用
TStringList *m_SL_timeStamp; // 項目追加日時
TStringList *m_SL_item; // 項目
//
void __fastcall saveAndRemove(void);
public: // ユーザー宣言
void __fastcall AddLogItem(TDateTime datDt, String item);
__fastcall TFormLogger(TComponent* Owner);
__fastcall ~TFormLogger();
};
//---------------------------------------------------------------------------
extern PACKAGE TFormLogger *FormLogger;
//---------------------------------------------------------------------------
#endif
LoggerUnit.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <DateUtils.hpp>
#include "LoggerUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormLogger *FormLogger;
//---------------------------------------------------------------------------
/*
v0.1 2017/11/09
- add [TimerProcess]
- add saveAndRemove()
- add getLogFileName()
- add getRoundedDateTime_eachNmin()
- add AddItem()
- add [m_SL_log]
- add [m_SL_timeStamp]
- add [m_SL_item]
- add ctor and dtor
*/
static const int kInterval_min = 5; // ログファイルの名前変更間隔
static const int kNumExtract = 5; // 取出す項目数
static const int kInterval_saveAndRemove_msec = 1000;
//---------------------------------------------------------------------------
// コンストラクタ・デストラクタ
//
__fastcall TFormLogger::TFormLogger(TComponent* Owner)
: TForm(Owner)
{
m_SL_item = new TStringList();
m_SL_timeStamp = new TStringList();
m_SL_log = new TStringList();
TimerProcess->Enabled = false;
TimerProcess->Interval = kInterval_saveAndRemove_msec; // msec
TimerProcess->Enabled = true;
}
__fastcall TFormLogger::~TFormLogger()
{
delete m_SL_item;
m_SL_item = NULL;
delete m_SL_timeStamp;
m_SL_timeStamp = NULL;
delete m_SL_log;
m_SL_log = NULL;
}
//---------------------------------------------------------------------------
// Public関数
//
void __fastcall TFormLogger::AddLogItem(TDateTime datDt, String item)
{
// 1. timestamp
String tmstp = DateTimeToStr(datDt);
m_SL_timeStamp->Add(tmstp);
// 2. item
m_SL_item->Add(item);
}
//---------------------------------------------------------------------------
// ファイルスコープstatic関数
//
static TDateTime getRoundedDateTime_eachNmin(TDateTime srcDt)
{
int dt_min = srcDt.FormatString(L"nn").ToInt();
int reduce_min = dt_min % kInterval_min; //
TDateTime res = IncMinute( srcDt, -(reduce_min) );
return res;
}
static String getLogFileName(TDateTime nowDt)
{
TDateTime dt = getRoundedDateTime_eachNmin(nowDt);
return L"log_t" + dt.FormatString(L"hhnn") + L".txt";
}
//---------------------------------------------------------------------------
// Private関数
//
void __fastcall TFormLogger::saveAndRemove(void)
{
int exracted = 0; // 処理済み項目数
String startfilename; // ファイル名変更のチェック用
String savefilename;
//
for(int idx=0; idx < kNumExtract; idx++) {
TDateTime dt = StrToDateTime(m_SL_timeStamp->Strings[idx]);
if (idx == 0) {
startfilename = getLogFileName(dt);
}
savefilename = getLogFileName(dt);
if (startfilename != savefilename) { // ファイル名変更時にそれまでの分を書出す
m_SL_log->SaveToFile(startfilename);
m_SL_log->Clear();
break;
}
String line = dt.FormatString(L"yyyy/mm/dd hh:nn:ss") + L"," + m_SL_item->Strings[idx];
m_SL_log->Add(line);
exracted++;
}
m_SL_log->SaveToFile(savefilename);
for(int loop=0; loop < exracted; loop++) {
m_SL_item->Delete(0);
m_SL_timeStamp->Delete(0);
}
}
//---------------------------------------------------------------------------
// IDE で管理されるコンポーネント
//
void __fastcall TFormLogger::TimerProcessTimer(TObject *Sender)
{
String item = L"";
if (m_SL_item->Count < kNumExtract) {
return;
}
// TODO:資源のロック開始
saveAndRemove();
// TODO:資源のロック解除
}
//---------------------------------------------------------------------------
使用例
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "LoggerUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Timer1->Enabled = false;
Timer1->Interval = 1000; // msec
Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
static int idx = 0;
String itm = IntToStr(idx);
FormLogger->AddLogItem(Now(), itm);
idx++;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
FormLogger->Show();
}
//---------------------------------------------------------------------------
結果例
log_t1655.txt
2017/11/09 16:57:16,0
2017/11/09 16:57:17,1
2017/11/09 16:57:18,2
2017/11/09 16:57:19,3
2017/11/09 16:57:20,4
2017/11/09 16:57:21,5
2017/11/09 16:57:22,6
2017/11/09 16:57:23,7
(中略)
2017/11/09 16:59:55,157
2017/11/09 16:59:56,158
2017/11/09 16:59:57,159
2017/11/09 16:59:58,160
2017/11/09 16:59:59,161
log_t1700.txt
2017/11/09 17:00:00,162
2017/11/09 17:00:01,163
2017/11/09 17:00:02,164
2017/11/09 17:00:03,165
(中略)
2017/11/09 17:02:49,328
2017/11/09 17:02:50,329
2017/11/09 17:02:51,330
2017/11/09 17:02:52,331
(ここでソフト停止)
備考
起動時に過去のログファイル読込みはしていないため、起動時に同じ名前の過去ログファイル内容は消えてしまう。
AddLogItem()は高頻度(1秒など)で実施されるという前提。低頻度(N分ごとなど)の場合は5回のAddLogItem()が実施される間隔が長くなる。データ消失に備えて保存処理のタイミングを変えることが望まれる。
保存ファイル名や保存先フォルダ指定などを追加すると、今後色々なプロジェクトで使い回ししやすくなるだろう。
static定義があるので、マルチインスタンスに対応していない。
クラスメンバー変数に移す方が役立つだろう。