LoginSignup
0
1

More than 5 years have passed since last update.

C++ Builder XE4, 10.2 Tokyo > ログForm > ファイル書込み (ファイル名はN分ごとに切替える)

Last updated at Posted at 2017-11-09
動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)

処理

  • 装置などからデータが適宜追加される
    • 例: 1000msecごとに1個ずつ
  • データを適当な個数で取出しファイルに書出す
    • 例: 5秒ごとに5個ずつ
  • ファイル名はN分ごとに変更する

関連

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定義があるので、マルチインスタンスに対応していない。
クラスメンバー変数に移す方が役立つだろう。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1