LoginSignup
0
2

More than 5 years have passed since last update.

C++ Builder XE4, 10.2 Tokyo > ファイル名から日付を取得 + 指定の日付以前のファイルを削除 > v0.1..v0.3

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

ファイル名に日付が入っている状況で、指定日付以前のファイルを削除する処理。

対象ファイル

bash > Brace Expansionで日付のダミーファイルを作る | ファイル名失敗時: MinGW32でファイルを消す
にて作ったファイル。

v0.1, v0.2

code

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <IOUtils.hpp>
#include <memory>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

/*
v0.2 2017/10/17
  - リストの対象ファイルを削除 (ゴミ箱には行かない)
  - isDateBefore()追加
  - getFileDateTime()追加
v0.1 2017/10/17
  - 対象フォルダにあるファイルリストを取得
*/


String kTargetFolder = L"D:\\WORK\\filedelete_171017";
TDateTime kLastDate = VarToDateTime("2017/01/15 00:00:00"); // Note: VarToDateTime()使用時はLマクロにしない

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

static TDateTime getFileDate(String filePath)
{
    String filename = ExtractFileName(filePath);
    // filename:
    //   例:"X_20170131.csv" (2017 Jan. 31のファイル)

    String strdt = filename.SubString(3, 8); // 3: yyyyの開始インデックス

    // 12345678
    // yyyymmdd
    strdt.Insert("/", 7); // mmとddの間
    strdt.Insert("/", 5); // yyyyとmmの間

    OutputDebugString(filename.c_str());

    return VarToDateTime(strdt + L" 00:00:00");
}

static bool isDateBefore(String filepath, TDate lastDate)
{
    TDateTime trgt;
    try {
        trgt = getFileDate(filepath);
    } catch (...) {
        return false; // ファイル名が日付型でない場合
    }
    if (trgt > lastDate) {
        return false;
    }
    return true;
}

void __fastcall TForm1::dbgB_getListClick(TObject *Sender)
{
    String searchPattern = L"*.csv";
    TSearchOption option = TSearchOption::soAllDirectories;

    TStringDynArray fileList = TDirectory::GetFiles(kTargetFolder, searchPattern, option);
    int allcnt = fileList.Length;

    std::unique_ptr<TStringList> lst(new TStringList);

    TDateTime filedt;
    for(int idx = 0; idx < fileList.Length; idx++) {
        if (isDateBefore(fileList[idx], kLastDate) == false) {
            continue;
        }
        lst->Add(fileList[idx]);

        TFile::Delete(fileList[idx]); /***********************/
    }

    String msg = IntToStr(lst->Count) + L"/" + IntToStr(allcnt);
    OutputDebugString(msg.c_str());

    Memo1->Lines->Assign(lst.get());
}
//---------------------------------------------------------------------------

実行結果

2017/01/15までのファイルが削除される。

備考

TFile::Delete()の場合、ごみ箱に行かずに削除される
(Shift + Deleteと同じ)。

TFile::Move()でごみ箱に移動しようかと検討したが、ごみ箱のパスを取得する方法が見つかっていない。
関連: https://qiita.com/7of9/items/7bb5d9837c696754995d

v0.3

  • 最終日だけでなく、最終日と日数に変更
  • 処理を関数化
Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <IOUtils.hpp>
#include <DateUtils.hpp>
#include <memory>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

/*
v0.3 2017/10/17
    - change to range
        + isInRange() takes [days] arg
        + refactor > rename isDateBefore() to isInRange()
    - deletePastFiles()追加
v0.2 2017/10/17
    - リストの対象ファイルを削除 (ゴミ箱には行かない)
    - isDateBefore()追加
    - getFileDateTime()追加
v0.1 2017/10/17
    - 対象フォルダにあるファイルリストを取得
*/


String kTargetFolder = L"D:\\WORK\\filedelete_171017";
TDateTime kLastDate = VarToDateTime("2017/01/15 00:00:00"); // Note: VarToDateTime()使用時はLマクロにしない

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

static TDateTime getFileDate(String filePath)
{
    String filename = ExtractFileName(filePath);
    // filename:
    //   例:"X_20170131.csv" (2017 Jan. 31のファイル)

    String strdt = filename.SubString(3, 8); // 3: yyyyの開始インデックス

    // 12345678
    // yyyymmdd
    strdt.Insert("/", 7); // mmとddの間
    strdt.Insert("/", 5); // yyyyとmmの間

    OutputDebugString(filename.c_str());

    return VarToDateTime(strdt + L" 00:00:00");
}

static bool isInRange(String filepath, TDate lastDate, int days)
{
    TDateTime trgt;
    TDateTime startdt = IncDay(lastDate, -(days - 1));

    try {
        trgt = getFileDate(filepath);
    } catch (...) {
        return false; // ファイル名が日付型でない場合
    }
    if (trgt < startdt) {
        return false;
    }
    if (trgt > lastDate) {
        return false;
    }
    return true;
}

void __fastcall TForm1::deletePastFiles(String filePattern, TDateTime lastDate, int days, String targetDir, TStringList *delList)
{
    TSearchOption option = TSearchOption::soAllDirectories;

    TStringDynArray fileList = TDirectory::GetFiles(kTargetFolder, filePattern, option);
    int allcnt = fileList.Length;

    for(int idx = 0; idx < fileList.Length; idx++) {
        if (isInRange(fileList[idx], lastDate, days) == false) {
            continue;
        }
        if (delList != NULL) {
            delList->Add(fileList[idx]);
        }

        TFile::Delete(fileList[idx]); // ごみ箱に行かずに消える
    }
}

void __fastcall TForm1::dbgB_getListClick(TObject *Sender)
{
    int days = 10; // テスト用
    std::unique_ptr<TStringList> lst(new TStringList);

    deletePastFiles(L"*.csv", kLastDate, /*days=*/days, /*targetDir=*/kTargetFolder, lst.get());
    Memo1->Lines->Assign(lst.get());
    String msg = IntToStr(lst->Count) + L" deleted";
    OutputDebugString(msg.c_str());
}
//---------------------------------------------------------------------------

1月6日から1月15日のファイルを消すようになった。

0
2
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
2