C++ Builder > How to check file deletion/modification time

```txt:動作環境
C++ Builder XE4
```

## Purpose

To know when the file is deleted/modified.

## v0.1
### Implementation

**Check interval is 100msec**.

```Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Vcl.Dialogs.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// 
	TButton *B_clear;
	TMemo *Memo1;
	TTimer *Timer1;
	TEdit *E_filename;
	TOpenDialog *OpenDialog1;
	TButton *B_selectFile;
	TButton *B_start;
	void __fastcall FormShow(TObject *Sender);
	void __fastcall Timer1Timer(TObject *Sender);
	void __fastcall B_clearClick(TObject *Sender);
	void __fastcall B_startClick(TObject *Sender);
	void __fastcall B_selectFileClick(TObject *Sender);
private:	//
	void __fastcall CheckFileModification(void);
public:		//
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
```

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

#include <vcl.h>
#pragma hdrstop

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

__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
	Memo1->Clear();
	E_filename->Text = L"";
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
	CheckFileModification();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::CheckFileModification(void)
{
	static TDateTime preDt;
	static bool isDeleted = false;

	if (E_filename->Text.Length() == 0) {
		return;
	}

	if (FileExists(E_filename->Text) == false) {
		if (isDeleted == false) {
			isDeleted = true;
			Memo1->Lines->Add(L"Deleted on " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));
		}
		return;
	}

	TDateTime curDt;
	FileAge(E_filename->Text, curDt);
	if (preDt != curDt) {
		isDeleted = false;
		preDt = curDt;
		Memo1->Lines->Add(L"Modified on " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));
	}
}


void __fastcall TForm1::B_clearClick(TObject *Sender)
{
	Memo1->Clear();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::B_startClick(TObject *Sender)
{
	Timer1->Enabled = false;
	Timer1->Interval = 100; // msec
	Timer1->Enabled = true;

	B_start->Caption = L"Started";
}
//---------------------------------------------------------------------------

void __fastcall TForm1::B_selectFileClick(TObject *Sender)
{
	if (OpenDialog1->Execute() == false) {
		return;
	}

	E_filename->Text = OpenDialog1->FileName;
}
//---------------------------------------------------------------------------
```

### How to use

1. Select the target file with [Browse]
2. Start the scan with [Start]
3. Use [Log Clear] to clear the log
    - **only if necessary**

To change the target file, just restart the software.

### Example

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/b18d6b2b-da52-daf0-ca6d-c9895ee1cdf1.png)


### download

v0.1: https://www.dropbox.com/s/f9mbj2dxpadkdvt/FileModifyChecker_170810.exe?dl=0


## v0.2 

added following features

- Copy file feature
    - with the timestamp of the modification
- Combobox to change [check interval]

### code 

```Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Vcl.Dialogs.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// coponents managed by IDE
	TButton *B_clear;
	TMemo *Memo1;
	TTimer *Timer1;
	TEdit *E_filename;
	TOpenDialog *OpenDialog1;
	TButton *B_selectFile;
	TButton *B_start;
	TCheckBox *CHK_copyFile;
	TComboBox *CB_interval_msec;
	TLabel *Label1;
	void __fastcall FormShow(TObject *Sender);
	void __fastcall Timer1Timer(TObject *Sender);
	void __fastcall B_clearClick(TObject *Sender);
	void __fastcall B_startClick(TObject *Sender);
	void __fastcall B_selectFileClick(TObject *Sender);
private:	// user declaration
	void __fastcall CheckFileModification(void);
	void __fastcall BackupFile(void);
public:		// user declaration
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
```

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

#include <vcl.h>
#pragma hdrstop

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

/*
v0.2 Aug. 11, 2017
	- add check interval combobox
	- add copy file feature [optional]
v0.1 Aug. 10, 2017
	- just display timestamps of [modification/deletion]
*/

__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
	Memo1->Clear();
	E_filename->Text = L"";
	CB_interval_msec->ItemIndex = 0;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
	CheckFileModification();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::BackupFile(void)
{
	if (CHK_copyFile->Checked == false) {
		return;
	}

	String fromfile = E_filename->Text; // original file (e.g. .git/config)
	String tofile; // backup file (e.g. config_20170811_123045_314)

	String curDir = GetCurrentDir();
	String timeStamp = Now().FormatString(L"yyyymmdd_hhnnss_zzz");
	tofile = curDir + L"\\" + ExtractFileName(fromfile);
	String ext = ExtractFileExt(fromfile);
	int len_subtracted = tofile.Length() - ext.Length();
	tofile = tofile.SubString(0, len_subtracted); // without extension
	tofile = tofile + L"_" + timeStamp + ext; // e.g. config_20170811_123045_314

	//Memo1->Lines->Add(Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));
	TFile::Copy(fromfile, tofile, /* overwrite=*/true); // about 2msec for copying a textfile (35 bytes)
	//Memo1->Lines->Add(Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));
}

void __fastcall TForm1::CheckFileModification(void)
{
	static TDateTime preDt;
	static bool isDeleted = false;

	if (E_filename->Text.Length() == 0) {
		return;
	}

	if (FileExists(E_filename->Text) == false) {
		if (isDeleted == false) {
			isDeleted = true;
			Memo1->Lines->Add(L"Deleted on " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));
		}
		return;
	}

	TDateTime curDt;
	FileAge(E_filename->Text, curDt);
	if (preDt != curDt) {
		isDeleted = false;
		preDt = curDt;
		BackupFile();
		Memo1->Lines->Add(L"Modified on " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));
	}
}

void __fastcall TForm1::B_clearClick(TObject *Sender)
{
	String msg = L"Clear log?";

	if (Application->MessageBox(msg.c_str(), L"Confirmation",MB_OKCANCEL | MB_DEFBUTTON2) == idCancel) {
		return;
	}

	Memo1->Clear();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::B_startClick(TObject *Sender)
{
	Timer1->Enabled = false;
	int idx = CB_interval_msec->ItemIndex;
	int itvl_msec = StrToIntDef(CB_interval_msec->Items->Strings[idx], 100);
	Timer1->Interval = itvl_msec;
	Timer1->Enabled = true;

	// just disalbe for not handling [restart] with other conditions
	B_start->Caption = L"Started";
	CB_interval_msec->Enabled = false;
	CHK_copyFile->Enabled = false;
	B_selectFile->Enabled = false;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::B_selectFileClick(TObject *Sender)
{
	if (OpenDialog1->Execute() == false) {
		return;
	}

	E_filename->Text = OpenDialog1->FileName;
}
//---------------------------------------------------------------------------
```

### How to use

Use the .exe file in a some folder, because the [Copyfile] feature will copy the target file to the folder where the application is executed.

1. Select the target file with [Browse]
2. Check the [Copyfile] if the file copy is desired
3. Select check interval
4. Start the scan with [Start]
5. Use [Log Clear] to clear the log
    - **only if necessary**

To change the target file, just restart the software.


### Example

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/283f2c61-2b03-3031-f0c0-1421f56fd379.png)

![qiita2.png](https://qiita-image-store.s3.amazonaws.com/0/32870/b3e03a00-c26d-6682-39aa-1180ba7fce57.png)

```sample_170810_20170811_130649_746.txt
aaabbb
dffd
cccfdsfd
fad
fds
d

```

```sample_170810_20170811_130710_790.txt
aaabbb
dffd
cccfdsfd
fad
fds
d
hello world

```

### Disclaimer

**Copy file feature will take the copy of the file.
If the target file is highly-frequently modified, and the copy feature works so frequently, it may cause a file-lock.**

**Please do not use this feature for your daily operational work, and use it only for test.**

### download

v0.2 https://www.dropbox.com/s/hk354a3djydd627/FileModifyChecker_170810.exe?dl=0