|
Delphi Programming / Object Pascal
[掲載 2007年04月01日] [更新 2016年10月01日] Delphi サンプルプログラム集 |
780_ファイル情報の取得と日時・属性の変更等 |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
|
780_FileInfoListETC.zip [8,732 KB] 2016年10月01日版 (EXE 同梱) |
- 2013年02月16日
- コードの整備と,Windows 7 U64(SP1) + Delphi XE Pro での動作確認
Delphi 2007 以前でも最小限の変更で利用可能なコードとした
- 2016年09月28日
- ディスク上のファイルサイズを取得するサンプルを追加
|
ファイルの情報,指定フォルダ内のファイルリストを取得したり,フォルダ内のファイルの合計サイズを取得するサンプルプログムです.ファイルの日時や属性を変更するコードもテストしてみました.
Delphi 2010 以降で,同様の操作をするためのコードは,[817_ディレクトリとファイルのリスト] の記事を参考にしてください. |
ファイルのサイズだけを取得するのであれば,GetFileSizeEx, TFileStream を使用しても取得できます.あるいは TMemoryStream に呼び込めば,その TMemoryStream のサイズから取得できます.
以下の記事を参考にしてください.
また,上のリンクの uIOUtilsEx を使用すると TFile.GetSize で簡単に取得できます. |
ファイルの更新日時の取得だけであれば,以下のように FileAge 関数か TFile.GetLastWriteTime メソッドを使用した方法が最も簡単ではないかと思われます. |
[備考]
下のコードで使用している DateTimeToStr 関数は,ミリ秒の値は取得しません.また,時刻の値が 0 の時は,時刻は表示しません.
FileGetDate
と FileDateToDateTime を使用するコードで取得する値は,ミリ秒の値が 0 となるだけでなく,1 ~ 2 数秒程度の誤差を伴うことがあります.おそらく,ファイルのタイムスタンプにミリ秒の値が存在する時にこの現象が発生するのではないかと思われますが,詳細は不明です.このことが確認できるように,参考としてコードを掲載しておきます.
実務で FileGetDate と FileDateToDateTime を使用するのは避けた方が無難と思われます.
|
|
図1
ファイルの更新日時の取得結果
- 以下の関数類を使用した結果
FileAge 関数
FileGetDate 関数
TFile.GetLastWriteTime メソッド
|
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
OpenDialog1.InitialDir := ExtractFileDir(Application.ExeName);
end;
//=============================================================================
// ファイルのタイムスタンプ(更新日時)の取得
// System.SysUtils.FileAgeを使用する例
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFilePath : String;
LFileDate : TDateTime;
begin
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
OpenDialog1.InitialDir := ExtractFileDir(OpenDialog1.FileName);
LFilePath := OpenDialog1.FileName;
if FileAge(LFilePath, LFileDate, True) then begin
ShowMessage(DateTimeToStr(LFileDate));
end;
end;
//=============================================================================
// ファイルのタイムスタンプ(更新日時)の取得
// IOUtils.TFile.GetLastWriteTime メソッドを使用する例
//
// usesにIOUtilsが必要(Delphi 2010以降)
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LFilePath : String;
LFileDate : TDateTime;
begin
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
OpenDialog1.InitialDir := ExtractFileDir(OpenDialog1.FileName);
LFilePath := OpenDialog1.FileName;
LFileDate := IOUtils.TFile.GetLastWriteTime(LFilePath);
ShowMessage(DateTimeToStr(LFileDate));
end;
//=============================================================================
// ファイルのタイムスタンプ(更新日時)の取得
// System.SysUtils.FileGetDateを使用する例
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
LFilePath : String;
LHandle : Integer;
LFileiDate : Integer;
LFileDate : TDateTime;
begin
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
OpenDialog1.InitialDir := ExtractFileDir(OpenDialog1.FileName);
LFilePath := OpenDialog1.FileName;
LHandle := FileOpen(LFilePath, fmOpenRead);
try
LFileiDate := FileGetDate(LHandle);
LFileDate := FileDateToDateTime(LFileiDate);
ShowMessage(DateTimeToStr(LFileDate));
finally
FileClose(LHandle);
end;
end;
01_指定ファイルの情報取得 ( SHGetFileInfo を使用 ) |
シェル関数の SHGetFileInfo を使用した例です.
ファイルのハンドルを CreateFile で取得し,このハンドルを使用して,GetFileTime 関数でファイルの作成日時等の情報を取得します.このサンプルのコードでは,フォルダの情報は,フォルダ名以外は取得できません. |
|
図2
設計時画面
|
|
図3
ファイルの選択
- ファイル選択ダイアログで,情報を取得したいファイルを選択
|
|
図4
実行結果
|
リスト2
指定ファイルの情報を取得 (SHGetFileInfo 使用) |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
CheckBox3: TCheckBox;
CheckBox4: TCheckBox;
OpenDialog1: TOpenDialog;
LabeledEdit1: TLabeledEdit;
LabeledEdit2: TLabeledEdit;
LabeledEdit3: TLabeledEdit;
LabeledEdit4: TLabeledEdit;
LabeledEdit5: TLabeledEdit;
LabeledEdit6: TLabeledEdit;
Image1: TImage;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
function FileTimeToDateTime(ATime: TFileTime): TDateTime;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
ShellApi;
{$R *.dfm}
//=============================================================================
// ファイルを選択して情報取得
// SHGetFileInfoを使用した例
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFileInfo : TSHFileInfo;
LFileName : String;
LFileHandle : THandle;
LAttributes : Integer;
LDateTime : TDateTime;
LCreateTime : TFileTime;
LAccessTime : TFileTime;
LModifyTime : TFileTime;
LIcon : TIcon;
begin
OpenDialog1.InitialDir := ExtractFileDir(Application.ExeName);
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
LabeledEdit1.Text := '';
LabeledEdit2.Text := '';
LabeledEdit3.Text := '';
LabeledEdit4.Text := '';
LabeledEdit5.Text := '';
LabeledEdit6.Text := '';
LFileName := OpenDialog1.FileName;
//選択したファイル名
LabeledEdit1.Text := LFileName;
//表示名の取得
SHGetFileInfo(PChar(LFileName), 0, LFileInfo, SizeOf(LFileInfo), SHGFI_DISPLAYNAME);
LabeledEdit2.Text := LFileInfo.szDisplayName;
//ファイル種別の取得
SHGetFileInfo(PChar(LFileName), 0, LFileInfo, SizeOf(LFileInfo), SHGFI_TYPENAME);
LabeledEdit3.Text := LFileInfo.szTypeName;
//ファイルに関連づいたアイコンの取得
LIcon := TIcon.Create;
try
SHGetFileInfo(PChar(LFileName),
FILE_ATTRIBUTE_DIRECTORY,
LFileInfo,
SizeOf(LFileInfo),
SHGFI_ICON);
LIcon.Handle := LFileInfo.hIcon;
Image1.Picture.Assign(LIcon);
finally
FreeAndNil(LIcon);
end;
// ファイル属性の取得
LAttributes := GetFileAttributes(PChar(LFileName));
CheckBox1.Checked := Bool(LAttributes and FILE_ATTRIBUTE_READONLY);
CheckBox2.Checked := Bool(LAttributes and FILE_ATTRIBUTE_HIDDEN);
CheckBox3.Checked := Bool(LAttributes and FILE_ATTRIBUTE_SYSTEM);
CheckBox4.Checked := Bool(LAttributes and FILE_ATTRIBUTE_ARCHIVE);
//ファイルハンドルを使用してファイルの日付関係の値を取得
LFileHandle := Windows.CreateFile(PChar(LFileName),
GENERIC_READ,
0,
nil,
OPEN_ALWAYS,
0,
0);
//フォルダの場合は失敗する
if LFileHandle <> INVALID_HANDLE_VALUE then begin
try
// タイムスタンプを取得
GetFileTime(LFileHandle, @LCreateTime, @LAccessTime, @LModifyTime);
//作成日
LDateTime := FileTimeToDateTime(LCreateTime);
LabeledEdit4.Text := FormatDateTime('yyyy年mm月dd日 hh時nn分', LDateTime);
//最終更新日
LDateTime := FileTimeToDateTime(LModifyTime);
LabeledEdit5.Text := FormatDateTime('yyyy年mm月dd日 hh時nn分', LDateTime);
//最終アクセス日
LDateTime:=FileTimeToDateTime(LAccessTime);
LabeledEdit6.Text := FormatDateTime('yyyy年mm月dd日 hh時nn分', LDateTime);
finally
CloseHandle(LFileHandle);
end;
end;
end;
//=============================================================================
// TFileTime型の値をDelphiのTDateTime型に変換する関数
//=============================================================================
function TForm1.FileTimeToDateTime(ATime: TFileTime): TDateTime;
var
LSystemTime : TSystemTime;
LTempTime : TFileTime;
begin
try
//FileTime形式(世界協定時刻)を地域にあわせる
FileTimeToLocalFileTime(ATime, LTempTime);
//FileTime形式をSystemTime形式にする
FileTimeToSystemTime(LTempTime, LSystemTime);
//SystemTime形式をDelphiのTDateTime形式に変換
Result := SystemTimeToDateTime(LSystemTime);
except
Result := 0;
end;
end;
end.
02_指定ファイルの情報取得 ( FindFirst と SHGetFileInfo を使用 ) |
FindFirst 関数を用いた例です.ただし,ファイルのアイコンの取得には SHGetFileInfo 関数を使用しています.
FindFirst 関数で,該当ファイルの情報を,TSHFileInfo 構造体 (レコード型) に取得し,そこからファイルの属性と作成日時等を取得します.このサンプルは,上のサンプルと違い,フォルダの情報も取得できます. |
|
図5
設計時画面 |
|
図6
実行結果
|
リスト3
指定ファイルの情報取得 (FindFirst 使用) |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
CheckBox3: TCheckBox;
CheckBox4: TCheckBox;
OpenDialog1: TOpenDialog;
LabeledEdit1: TLabeledEdit;
LabeledEdit2: TLabeledEdit;
LabeledEdit3: TLabeledEdit;
LabeledEdit4: TLabeledEdit;
LabeledEdit5: TLabeledEdit;
Image1: TImage;
LabeledEdit6: TLabeledEdit;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
function FileTimeToDateTime(ATime: TFileTime): TDateTime;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
ShellApi;
{$R *.dfm}
//=============================================================================
// ファイルを選択して情報取得
// FindFirstを使用した例(アイコンの取得にはSHGetFileInfoを使用)
// フォルダの情報取得も可能
//
// SHGetFileInfoにはusesにShellApiが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFileInfo : TSHFileInfo;
LFileName : String;
LAttributes : Cardinal;
LDateTime : TDateTime;
LFileSize : Int64;
LIcon : TIcon;
LSearchRec : TSearchRec;
LFileData : TWin32FindData;
begin
OpenDialog1.InitialDir := ExtractFileDir(Application.ExeName);
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
LabeledEdit1.Text := '';
LabeledEdit2.Text := '';
LabeledEdit4.Text := '';
LabeledEdit5.Text := '';
LabeledEdit6.Text := '';
LFileName := OpenDialog1.FileName;
//選択したファイル名
LabeledEdit1.Text := LFileName;
//ファイルに関連づいたアイコンの取得
LIcon := TIcon.Create;
try
SHGetFileInfo(PChar(LFileName),
FILE_ATTRIBUTE_DIRECTORY,
LFileInfo,
SizeOf(LFileInfo),
SHGFI_ICON);
LIcon.Handle := LFileInfo.hIcon;
Image1.Picture.Assign(LIcon);
finally
FreeAndNil(LIcon);
end;
if FindFirst(LFileName, faAnyFile, LSearchRec) = 0 then begin
//TWin32FindData構造体
LFileData := LSearchRec.FindData;
LabeledEdit2.Text := LSearchRec.Name;
//ファイルまたフォルダの属性を取得
LAttributes := LFileData.dwFileAttributes;
CheckBox1.Checked := Bool(LAttributes and FILE_ATTRIBUTE_READONLY);
CheckBox2.Checked := Bool(LAttributes and FILE_ATTRIBUTE_HIDDEN);
CheckBox3.Checked := Bool(LAttributes and FILE_ATTRIBUTE_SYSTEM);
CheckBox4.Checked := Bool(LAttributes and FILE_ATTRIBUTE_ARCHIVE);
//作成日
LDateTime := FileTimeToDateTime(LFileData.ftCreationTime);
LabeledEdit3.Text := FormatDateTime('yyyy年mm月dd日 hh時nn分', LDateTime);
//最終更新日
LDateTime := FileTimeToDateTime(LFileData.ftLastWriteTime);
LabeledEdit4.Text := FormatDateTime('yyyy年mm月dd日 hh時nn分', LDateTime);
//最終アクセス日
LDateTime := FileTimeToDateTime(LFileData.ftLastAccessTime);
LabeledEdit5.Text := FormatDateTime('yyyy年mm月dd日 hh時nn分', LDateTime);
//ファイルサイズ(TSearchRec.Size)
LFileSize := LSearchRec.Size;
LabeledEdit6.Text := FormatFloat('##,##0 バイト', LFileSize);
end;
FindClose(LSearchRec);
end;
//=============================================================================
// TFileTime型の値をDelphiのTDateTime型に変換する関数
//=============================================================================
function TForm1.FileTimeToDateTime(ATime: TFileTime): TDateTime;
var
LSystemTime : TSystemTime;
LTempTime : TFileTime;
begin
try
//FileTime形式(世界協定時刻)を地域にあわせる
FileTimeToLocalFileTime(ATime, LTempTime);
//FileTime形式をSystemTime形式にする
FileTimeToSystemTime(LTempTime, LSystemTime);
//SystemTime形式をDelphiのTDateTime形式に変換
Result := SystemTimeToDateTime(LSystemTime);
except
Result := 0;
end;
end;
end.
03_指定フォルダ内のファイルとフォルダの一覧を取得 |
findFirst と FindNext 関数を使用して,指定フォルダ内のファイルとフォルダの一覧を取得するサンプルプログラムです.
指定したフォルダ直下のものだけ取得して表示します.サブフォルダ内は検索しません.
このサンプルや,次のサンプルのようなコードで,フォルダやファイルのリストを取得できますが,ファイル数が多くなると表示に時間がかかるようになります.そのような場合は,仮想リストビュー方式を使用することになります.更に多くなる場合は,ファイルそのもののデータベース化ということになるでしょう. |
|
図7
設計時画面
|
|
図8
フォルダを選択
- ここでは,このプロジェクトのフォルダを選択
- 本ページのサンプルでは,フォルダの指定用に,SelectDirectory を使用しているが,Delphi 2007 以上であれば,TFileOpenDialog の方がいいかも知れない
|
|
図9
実行結果
|
リスト4
指定フォルダ内のファイルとフォルダをリスト |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
ListView1: TListView;
Panel2: TPanel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
FFilesCount : Integer;
procedure GetFilesList(APath: String; FileList: TStringList);
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
FileCtrl;
{$R *.dfm}
//=============================================================================
// 指定フォルダ内のファイルとフォルダを表示
// FFilesCountはファイル数(フォルダ数を含む)でグローバル変数
//
// SelectDirectoryの使用にはusesにFileCtrlが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFileList : TStringList;
LPath : String;
i : Integer;
begin
FFilesCount := 0;
Panel1.Caption := '';
LPath := ExtractFileDir(Application.ExeName);
//Delphi 2007より前には,最後の引数がない
//Vista以降で FileCtrl.SelectDirectory('フォルダ指定', '', SrcDir, [sdNewUI])
//でダイアログを表示すると,指定したフォルダ位置までスクロールしてくれない
if SelectDirectory('検索フォルダ指定', '', LPath, []) then begin
LFileList := TStringList.Create;
LFileList.Clear;
ListView1.Items.Clear;
try
GetFilesList(LPath, LFileList);
ListView1.Items.BeginUpdate;
for i := 0 to LFileList.Count - 1 do begin
ListView1.Items.Add.Caption := LFileList[i];
end;
ListView1.Items.EndUpdate;
finally
FreeAndNil(LFileList);
end;
end;
Panel1.Caption := 'ファイル数 : ' + IntToStr(FFilesCount);
end;
//=============================================================================
// APathで指定するフォルダ内の全てのファイルを検索するメソッド
// サブフォルダ内は検索しない
//=============================================================================
procedure TForm1.GetFilesList(APath: String; FileList: TStringList);
var
LSearchPath : String;
LSearchRec : TSearchRec;
begin
LSearchPath:=IncludeTrailingPathDelimiter(APath) + '*.*';
if FindFirst(LSearchPath, faAnyFile,LSearchRec) = 0 then begin
repeat
if not ((LSearchRec.Name = '..') or (LSearchRec.Name = '.')) then begin
FileList.Add(LSearchRec.Name);
Inc(FFilesCount);
end;
until FindNext(LSearchRec) <> 0;
FindClose(LSearchRec);
end;
end;
end.
04_指定フォルダ内 ( サブフォルダを含む ) のファイル一覧を取得 |
上のサンプルは,サブフォルダ内を検索しませんでしたが,こちらは,サブフォルダも含めて,指定フォルダ内のファイル全てをフルパスで表示します.
検索用の関数を再帰的に呼出すことで,サブフォルダも検索するようにしています. |
|
図10
設計時画面 |
|
図11
実行結果
|
リスト5
指定フォルダ内のファイルとフォルダをサブフォルダ内を含めて全てリスト |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
ListView1: TListView;
Panel2: TPanel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
FFilesCount : Integer;
procedure GetFilesListAll(APath: String; FileList: TStringList);
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
FileCtrl;
{$R *.dfm}
//=============================================================================
// 検索開始
// FFilesCountはファイル数でグローバル変数
//
// SelectDirectoryの使用にはusesにFileCtrlが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFileList : TStringList;
LBasePath : String;
i : Integer;
begin
FFilesCount := 0;
Panel1.Caption := '';
LBasePath := ExtractFileDir(Application.ExeName);
//Delphi 2007より前には,最後の引数がない
//Vista以降で FileCtrl.SelectDirectory('フォルダ指定', '', SrcDir, [sdNewUI])
//でダイアログを表示すると,指定したフォルダ位置までスクロールしてくれない
if SelectDirectory('検索フォルダ指定', '', LBasePath, []) then begin
LFileList := TStringList.Create;
try
LBasePath := IncludeTrailingPathDelimiter(LBasePath);
ListView1.Items.Clear;
LFileList.Clear;
GetFilesListAll(LBasePath, LFileList);
ListView1.Items.BeginUpdate;
for i := 0 to LFileList.Count - 1 do begin
ListView1.Items.Add.Caption := LFileList[i];
end;
ListView1.Items.EndUpdate;
finally
FreeAndNil(LFileList);
end;
end;
Panel1.Caption:='ファイル数 : ' + IntToStr(FFilesCount);
end;
//=============================================================================
// APathで指定するフォルダ内の全てのファイルを検索するメソッド
// サブフォルダ内も検索
//=============================================================================
procedure TForm1.GetFilesListAll(APath: String; FileList: TStringList);
var
LSearchPath : String;
LSearchRec : TSearchRec;
begin
if FindFirst(APath + '*.*', faAnyFile, LSearchRec) = 0 then begin
repeat
if not ((LSearchRec.Name = '..') or (LSearchRec.Name = '.')) then begin
if LSearchRec.Attr = faDirectory then begin
LSearchPath := IncludeTrailingPathDelimiter(APath+LSearchRec.Name);
//フォルダの場合は,この関数を再帰的に呼出して,そのフォルダ内を検索
GetFilesListAll(LSearchPath, FileList);
end else begin
//LSearchRec.Nameだけにすればファイル名のみ
FileList.Add(APath + LSearchRec.Name);
Inc(FFilesCount);
end;
end;
until FindNext(LSearchRec) <> 0;
FindClose(LSearchRec);
end;
end;
end.
サブフォルダも含めて,指定フォルダ内の拡張子が doc のファイルを検索して表示します. |
|
図12
設計時画面
|
|
図13
実行結果
|
リスト6
指定フォルダ内の指定拡張子のファイルのみリスト |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
ListView1: TListView;
Panel2: TPanel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
FFilesCount : Integer;
procedure GetFilesListAllExt(APath, Ext: String; FileList: TStringList);
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
FileCtrl;
{$R *.dfm}
//=============================================================================
// 拡張子が.docのファイルのみを検索
// FFilesCountはファイル数でグローバル変数
//
// SelectDirectoryの使用にはusesにFileCtrlが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFileList : TStringList;
LBasePath : String;
LFileExt : String;
i : Integer;
begin
FFilesCount := 0;
Panel1.Caption := '';
LBasePath := ExtractFileDir(Application.ExeName);
//Delphi 2007より前には,最後の引数がない
//Vista以降で FileCtrl.SelectDirectory('フォルダ指定', '', SrcDir, [sdNewUI])
//でダイアログを表示すると,指定したフォルダ位置までスクロールしてくれない
if SelectDirectory('検索フォルダ指定', '', LBasePath, []) then begin
LBasePath := IncludeTrailingPathDelimiter(LBasePath);
LFileExt := '.doc';
LFileList := TStringList.Create;
LFileList.Clear;
ListView1.Items.Clear;
try
GetFilesListAllExt(LBasePath, LFileExt, LFileList);
ListView1.Items.BeginUpdate;
ListView1.Columns[0].Width := 500;
for i := 0 to LFileList.Count - 1 do begin
ListView1.Items.Add.Caption := LFileList[i];
end;
ListView1.Items.EndUpdate;
finally
FreeAndNil(LFileList);
end;
end;
Panel1.Caption := 'ファイル数 : ' + IntToStr(FFilesCount);
end;
//=============================================================================
// APathで指定するフォルダ内の全てのファイルの中から拡張子がExtのファイルを検
// 索するメソッド
// サブフォルダ内も検索
//=============================================================================
procedure TForm1.GetFilesListAllExt(APath, Ext: String; FileList: TStringList);
var
LSearchPath : String;
LSearchRec : TSearchRec;
begin
if FindFirst(APath + '*.*', faAnyFile, LSearchRec) = 0 then begin
repeat
if not ((LSearchRec.Name = '..') or (LSearchRec.Name = '.')) then begin
if LSearchRec.Attr = faDirectory then begin
LSearchPath := IncludeTrailingPathDelimiter(APath+LSearchRec.Name);
//フォルダの場合は,この関数を再帰的に呼出して,そのフォルダ内を検索
GetFilesListAllExt(LSearchPath, Ext, FileList);
end else begin
if ExtractFileExt(LSearchRec.Name) = Ext then begin
FileList.Add(APath+LSearchRec.Name);
Inc(FFilesCount);
end;
end;
end;
until FindNext(LSearchRec) <> 0;
FindClose(LSearchRec);
end;
end;
end.
サブフォルダも含めて,指定フォルダ内の,ファイル名に東京という文字列を含むファイルを検索して表示します.ファイルのサイズと更新日時も表示するようにしてみました.また,表示されたファイル名をダブルクリックすると,そのファイルに関連付けされたアプリを起動します. |
- 図15
- このプロジェクト内を検索した実行結果
- ファイル名をダブルクリックすると,拡張子が .doc なのでワードが起動する
|
|
|
図16
ワードが起動
|
リスト7
指定フォルダ内のファイル名の部分一致検索 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
ListView1: TListView;
Panel2: TPanel;
Button1: TButton;
Panel1: TPanel;
procedure Button1Click(Sender: TObject);
procedure ListView1DblClick(Sender: TObject);
private
{ Private 宣言 }
FFilesCount : Integer;
procedure GetFilesListFindTitle(APath, FindText: String);
function FileTimeToDateTime(ATime:TFileTime): TDateTime;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
FileCtrl,
ShellAPI;
{$R *.dfm}
//=============================================================================
// 検索開始
// ファイル名に'東京'という文字列があるファイルのみを取得
// FFilesCountはファイル数でグローバル変数
//
// SelectDirectoryの使用にはusesにFileCtrlが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LBasePath : String;
LFindText : String;
begin
FFilesCount := 0;
Panel1.Caption := '';
LBasePath := ExtractFileDir(Application.ExeName);
//Delphi 2007より前には,最後の引数がない
//Vista以降で FileCtrl.SelectDirectory('フォルダ指定', '', SrcDir, [sdNewUI])
//でダイアログを表示すると,指定したフォルダ位置までスクロールしてくれない
if SelectDirectory('検索フォルダ指定', '', LBasePath, []) then begin
LBasePath := IncludeTrailingPathDelimiter(LBasePath);
LFindText := '東京';
ListView1.Items.Clear;
ListView1.MultiSelect := False;
ListView1.Items.BeginUpdate;
GetFilesListFindTitle(LBasePath, LFindText);
ListView1.Items.EndUpdate;
end;
Panel1.Caption := '該当ファイル数 : ' + IntToStr(FFilesCount);
end;
//=============================================================================
// APathで指定するフォルダ内(サブフォルダを含む)の全てのファイルの中からファイ
// ル名に指定の文字列を含むファイルをTListViewに表示
//=============================================================================
procedure TForm1.GetFilesListFindTitle(APath, FindText: String);
var
LSearchPath : String;
LSearchRec : TSearchRec;
LItem : TListItem;
LSize : Integer;
LDateTime : TDateTime;
LTempStr : String;
begin
if FindFirst(APath + '*.*', faAnyFile, LSearchRec) = 0 then begin
repeat
if not ((LSearchRec.Name = '..') or (LSearchRec.Name = '.')) then begin
if LSearchRec.Attr = faDirectory then begin
LSearchPath := IncludeTrailingPathDelimiter(APath+LSearchRec.Name);
//フォルダの場合は,この関数を再帰的に呼出して,そのフォルダ内を検索
GetFilesListFindTitle(LSearchPath, FindText);
end else begin
if Pos(FindText, LSearchRec.Name) <> 0 then begin
//ファイル名とフルパス名をListView1に追加
LItem := ListView1.Items.Add;
LItem.Caption := LSearchRec.Name;
LItem.SubItems.Add(APath+LSearchRec.Name);
//ファイルサイズ
LSize := LSearchRec.FindData.nFileSizeLow;
LTempStr := FormatFloat('###,##0', LSize) + ' バイト';
LItem.SubItems.Add(LTempStr);
//最終更新日
LDateTime := FileTimeToDateTime(LSearchRec.FindData.ftLastWriteTime);
LTempStr := FormatDateTime('yyyy年mm月dd日 hh時nn分', LDateTime);
LItem.SubItems.Add(LTempStr);
Inc(FFilesCount);
end;
end;
end;
until FindNext(LSearchRec) <> 0;
FindClose(LSearchRec);
end;
end;
//=============================================================================
// TFileTime型の値をDelphiのTDateTime型に変換する関数
//=============================================================================
function TForm1.FileTimeToDateTime(ATime: TFileTime): TDateTime;
var
LSystemTime : TSystemTime;
LTempTime : TFileTime;
begin
try
//FileTime形式(世界協定時刻)を地域にあわせる
FileTimeToLocalFileTime(ATime, LTempTime);
//FileTime形式をSystemTime形式にする
FileTimeToSystemTime(LTempTime, LSystemTime);
//SystemTime形式をDelphiのTDateTime形式に変換
Result:=SystemTimeToDateTime(LSystemTime);
except
Result := 0;
end;
end;
//=============================================================================
// ダブルクリックしたら関連付けアプリを起動
// ShellExecuteはusesにShellApiが必要
//=============================================================================
procedure TForm1.ListView1DblClick(Sender: TObject);
var
LFileName : String;
begin
if ListView1.SelCount = 0 then exit;
LFileName := ListView1.Selected.SubItems[0];
ShellExecute(Handle, 'OPEN', PChar(LFileName), nil, nil, SW_SHOWNORMAL);
end;
end.
特に改めて紹介する内容ではありませんが,ファイルサイズの合計を取得するサンプルコードです.
単にファイルのサイズの値を加算しているだけです. |
|
図17
設計時画面
|
|
図18
実行結果
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
ListView1: TListView;
Panel2: TPanel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
FFilesCount : Integer;
FTotalSize : Int64;
procedure GetFilesListAll(APath: String);
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
FileCtrl;
{$R *.dfm}
//=============================================================================
// 検索開始
// FFilesCountはファイル数でグローバル変数
// FTotalSizeはファイルサイズの合計でグローバル変数
//
// SelectDirectoryの使用にはusesにFileCtrlが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LBasePath : String;
begin
FFilesCount := 0;
FTotalSize := 0;
Panel1.Caption := '';
LBasePath := ExtractFileDir(Application.ExeName);
if SelectDirectory('検索フォルダ指定', '', LBasePath, []) then begin
LBasePath := IncludeTrailingPathDelimiter(LBasePath);
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
GetFilesListAll(LBasePath);
ListView1.Items.EndUpdate;
end;
Panel1.Caption := 'ファイル数 : ' + IntToStr(FFilesCount) + ' '
+ '合計サイズ : ' + FormatCurr('###,##0', FTotalSize) + ' バイト';
end;
//=============================================================================
// APathで指定するフォルダ内の全てのファイルを検索するメソッド
// サブフォルダ内も検索して,ファイル数とサイズを計算
//=============================================================================
procedure TForm1.GetFilesListAll(APath: String);
var
LSearchPath : String;
LSearchRec : TSearchRec;
begin
if FindFirst(APath + '*.*', faAnyFile, LSearchRec) = 0 then begin
repeat
if not ((LSearchRec.Name = '..') or (LSearchRec.Name = '.')) then begin
if LSearchRec.Attr = faDirectory then begin
LSearchPath := IncludeTrailingPathDelimiter(APath + LSearchRec.Name);
//フォルダの場合は,この関数を再帰的に呼出して,そのフォルダ内を検索
GetFilesListAll(LSearchPath);
end else begin
//ファイル名のみListView1に追加
ListView1.Items.Add.Caption := LSearchRec.Name;
Inc(FFilesCount);
//サイズを加算
FTotalSize := FTotalSize+LSearchRec.FindData.nFileSizeLow;
end;
end;
until FindNext(LSearchRec) <> 0;
FindClose(LSearchRec);
end;
end;
end.
指定フォルダ内のファイルの作成日時,最終更新日時を,一括して変更するサンプルです.
サブフォルダ内のファイルやフォルダの日時も変更します.最終アクセス日時は変更しても意味がないので変更しません.
このサンプルでは,指定したフォルダそのものの日時も変更するようにしています.
Delphi 2010 で実装された TFile を使用すると,簡単にファイルの日時の取得や変更ができます.以下のリンクの記事を参考にしてください.
|
|
図19
設計時画面
|
|
図20
日付を変更したところ
- このプロジェクトフォルダ内の例
- DateTimePicker1 値の日付に変更
- 時刻表示はないが,現在の時刻に変更
|
|
図21
エクスプローラで確認
|
リスト9
指定フォルダ内のファイルの日時を一括変更 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
ListView1: TListView;
Panel3: TPanel;
Button1: TButton;
Button2: TButton;
DateTimePicker1: TDateTimePicker;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private 宣言 }
FFilesCount : Integer;
FBasePath : String;
procedure GetFilesListAll(APath: String);
procedure ChangeFilesDate(APath: String; AfterDateTime: TDateTime);
function DateTimeToFileTime(ATime: TDateTime): TFileTime;
function FileTimeToDateTime(ATime: TFileTime): TDateTime;
procedure SetFileTimeStamp(AFileName: String; AfterDateTime: TDateTime);
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
FileCtrl;
{$R *.dfm}
//=============================================================================
// 日付を本日にする
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
FBasePath := ExtractFileDir(Application.ExeName);
DateTimePicker1.DateTime := Now;
end;
//=============================================================================
// [ファイル一覧]ボタン
// FFilesCountはファイル数でグローバル変数
// FBasePathは検索開始フォルダ名でグローバル変数
//
// SelectDirectoryの使用にはusesにFileCtrlが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
FFilesCount := 0;
Panel1.Caption := '';
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
//Sender = nil は[日時変更]ボタンをクリックした時
if Sender <> nil then begin
//Delphi 2007より前には,最後の引数がない
//Vista以降で FileCtrl.SelectDirectory('フォルダ指定', '', SrcDir, [sdNewUI])
//でダイアログを表示すると,指定したフォルダ位置までスクロールしてくれない
if FileCtrl.SelectDirectory('フォルダ指定', '', FBasePath, []) then begin
Update;
end;
end;
FBasePath := IncludeTrailingPathDelimiter(FBasePath);
GetFilesListAll(FBasePath);
ListView1.Items.EndUpdate;
Button2.Enabled := ListView1.Items.Count > 0;
Panel1.Caption := 'ファイル数 : ' + IntToStr(FFilesCount);
end;
//=============================================================================
// [日付変更]ボタン
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LNewDateTime : TDateTime;
begin
LNewDateTime := DateTimePicker1.DateTime;
ChangeFilesDate(FBasePath, LNewDateTime);
//確認のために再表示
Button1Click(nil);
end;
//=============================================================================
// APathで指定するフォルダ内(サブフォルダも含む)の全てのファイルを検索して
// TListViewに表示する(ファイル名のみ)
//=============================================================================
procedure TForm1.GetFilesListAll(APath: String);
var
LSearchPath : String;
LSearchRec : TSearchRec;
LItem : TListItem;
LDateTime : TDateTime;
LTempStr : String;
begin
if FindFirst(APath + '*.*', faAnyFile, LSearchRec) = 0 then begin
repeat
if not ((LSearchRec.Name = '..') or (LSearchRec.Name = '.')) then begin
if LSearchRec.Attr = faDirectory then begin
LSearchPath := IncludeTrailingPathDelimiter(APath + LSearchRec.Name);
//フォルダの場合は,この関数を再帰的に呼出して,そのフォルダ内を検索
GetFilesListAll(LSearchPath);
end else begin
LItem := ListView1.Items.Add;
LItem.Caption := LSearchRec.Name;
//作成日
LDateTime := FileTimeToDateTime(LSearchRec.FindData.ftCreationTime);
LTempStr := FormatDateTime('yyyy/mm/dd hh:nn', LDateTime);
LItem.SubItems.Add(LTempStr);
Inc(FFilesCount);
end;
end;
until FindNext(LSearchRec) <> 0;
FindClose(LSearchRec);
end;
end;
//=============================================================================
// APathで指定するフォルダ内(サブフォルダも含めて)の日付を変更するメソッド
// 読み取り専用属性のファイルは変更できない
//=============================================================================
procedure TForm1.ChangeFilesDate(APath: String; AfterDateTime: TDateTime);
var
LSearchPath : String;
LSearchRec : TSearchRec;
begin
//現在のフォルダの日時も変更してしまうことにする
SetFileTimeStamp(APath, AfterDateTime);
if FindFirst(APath + '*.*', faAnyFile, LSearchRec) = 0 then begin
repeat
if not ((LSearchRec.Name = '..') or (LSearchRec.Name = '.')) then begin
if LSearchRec.Attr = faDirectory then begin
LSearchPath := IncludeTrailingPathDelimiter(APath + LSearchRec.Name);
SetFileTimeStamp(LSearchPath, AfterDateTime);
//フォルダの時は,このメソッドを再帰的に呼び出して設定
ChangeFilesDate(LSearchPath, AfterDateTime);
end else begin
SetFileTimeStamp(APath + LSearchRec.Name, AfterDateTime);
Inc(FFilesCount);
end;
end;
until FindNext(LSearchRec) <> 0;
FindClose(LSearchRec);
end;
end;
//=============================================================================
// TFileTime型の値をDelphiのTDateTime型に変換する関数
//=============================================================================
function TForm1.FileTimeToDateTime(ATime: TFileTime): TDateTime;
var
LSystemTime : TSystemTime;
LTempTime : TFileTime;
begin
try
//FileTime形式(世界協定時刻)を地域にあわせる
FileTimeToLocalFileTime(ATime, LTempTime);
//FileTime形式をSystemTime形式にする
FileTimeToSystemTime(LTempTime, LSystemTime);
//SystemTime形式をDelphiのTDateTime形式に変換
Result := SystemTimeToDateTime(LSystemTime);
except
Result := 0;
end;
end;
//=============================================================================
// DelphiのTDateTime型の値をTFileTime型に変換する関数
//=============================================================================
function TForm1.DateTimeToFileTime(ATime: TDateTime): TFileTime;
var
LSystemTime : TSystemTime;
LLocalFileTime : TFileTime;
begin
try
//TFileTimeをSystemTimeに変換
DateTimeToSystemTime(ATime, LSystemTime);
//SystemTimeをローカルのFileTimeに変換
SystemTimeToFileTime(LSystemTime, LLocalFileTime);
//最後にローカルの日時をGMT(世界協定時刻)に変換
LocalFileTimeToFileTime(LLocalFileTime, Result);
except
Result.dwLowDateTime := 0;
Result.dwHighDateTime := 0;
end;
end;
//=============================================================================
// ファイルやフォルダの日付を変更するメソッド
// 実行中の自分自身は変更できない
// AFileName : 日時を変更するファイルまたはフォルダ名
// LCreateTime : 作成日時
// LModifyTime : 更新日時
// アクセス日時は変更しても意味がないのでしない
//=============================================================================
procedure TForm1.SetFileTimeStamp(AFileName: String; AfterDateTime: TDateTime);
var
LHandle : THandle;
LCreateTime : TFileTime;
LModifyTime : TFileTime;
begin
LHandle := 0;
try
//デリミタは削除
AFileName := ExcludeTrailingPathDelimiter(AFileName);
LHandle := CreateFile(Pchar(AFileName),
GENERIC_WRITE,
FILE_SHARE_READ,
nil,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
0);
if LHandle > 0 then begin
LCreateTime := DateTimeToFileTIme(AfterDateTime);
LModifyTime := DateTimeToFileTIme(AfterDateTime);
//日付を変更する
SetFileTime(LHandle, Addr(LCreateTime), nil, Addr(LModifyTime));
end;
finally
CloseHandle(LHandle);
end;
end;
end.
続いてファイルの属性を変更してしまうサンプルコードです.ファイルの日付変更の部分を属性変更のコードにしたものです.ただし,このサンプルでは,Windows API の FindFirstFile と FindNextFile を使用してみました.
Delphi 2010 で実装された TFile を使用すると,簡単にファイルの属性の取得や変更ができます.以下のリンクの記事を参考にしてください.
|
|
図22
設計時画面
|
|
図23
フォルダを選択
- このフォルダ内のファイルの属性を変更
- 本ページのサンプルでは,フォルダの指定用に,SelectDirectory を使用しているが,Delphi 2007 以上であれば,TFileOpenDialog の方がいいかも知れない
|
|
図24
変更対象ファイル
- このプロジェクト内の BBB というフォルダ内のファイル
|
|
図25
属性変更
- NORMAL はファイルやフォルダの一般的な属性
R 読出し専用
H 隠しファイル
S システムファイル
A アーカイブ
- 属性を変更すると,次回ファイルの検索で取得できなくなることがある.その場合は,そのファイルを含むフォルダの属性を NORMAL にして,再度ファイル一覧を取得する
|
リスト10
指定フォルダ内のファイルの属性を一括変更 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
ListView1: TListView;
Panel2: TPanel;
Button1: TButton;
Button2: TButton;
Panel3: TPanel;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
CheckBox3: TCheckBox;
CheckBox4: TCheckBox;
CheckBox5: TCheckBox;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure CheckBox5Click(Sender: TObject);
private
{ Private 宣言 }
FFilesCount : Integer;
FBasePath : String;
procedure GetFilesListAll(APath: String);
procedure SetFilesListAttrib(APath: String; dmFileAttributes:Cardinal);
procedure SetFileAttrib(FileName:String; dmFileAttributes:Cardinal);
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
FileCtrl;
{$R *.dfm}
//=============================================================================
// [ファイル一覧]ボタン
// FFilesCountはファイル数でグローバル変数
// FBasePathは検索開始フォルダ名でグローバル変数
//
// SelectDirectoryの使用にはusesにFileCtrlが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
FFilesCount := 0;
Panel1.Caption := '';
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
//Sender = nil は[属性変更]ボタンをクリックした時
if Sender <> nil then begin
FBasePath := ExtractFileDir(Application.ExeName);
//Delphi 2007より前には,最後の引数がない
//Vista以降で FileCtrl.SelectDirectory('フォルダ指定', '', SrcDir, [sdNewUI])
//でダイアログを表示すると,指定したフォルダ位置までスクロールしてくれない
if SelectDirectory('検索フォルダ指定', '', FBasePath, []) then begin
FBasePath := IncludeTrailingPathDelimiter(FBasePath);
//フォルダの場合は,この関数を再帰的に呼出して,そのフォルダ内を検索
GetFilesListAll(FBasePath);
end;
end else begin
GetFilesListAll(FBasePath);
end;
ListView1.Items.EndUpdate;
Button2.Enabled:=ListView1.Items.Count > 0;
Panel1.Caption := 'ファイル数 : ' + IntToStr(FFilesCount);
end;
//=============================================================================
// [属性変更]ボタン
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LAttrib : Cardinal;
begin
LAttrib := 0;
if CheckBox5.Checked then begin
LAttrib := FILE_ATTRIBUTE_NORMAL;
end else begin
if CheckBox1.Checked = True then LAttrib := LAttrib or FILE_ATTRIBUTE_READONLY;
if CheckBox2.Checked = True then LAttrib := LAttrib or FILE_ATTRIBUTE_HIDDEN;
if CheckBox3.Checked = True then LAttrib := LAttrib or FILE_ATTRIBUTE_SYSTEM;
if CheckBox4.Checked = True then LAttrib := LAttrib or FILE_ATTRIBUTE_ARCHIVE;
end;
SetFilesListAttrib(FBasePath, LAttrib);
//確認のために再表示
Button1Click(nil);
end;
//=============================================================================
// FILE_ATTRIBUTE_NORMALは単独での指定しかできないので他の設定は無しにする
//=============================================================================
procedure TForm1.CheckBox5Click(Sender: TObject);
begin
if CheckBox5.Checked then begin
CheckBox1.Checked := False;
CheckBox2.Checked := False;
CheckBox3.Checked := False;
CheckBox4.Checked := False;
end;
CheckBox1.Enabled := not CheckBox5.Checked;
CheckBox2.Enabled := not CheckBox5.Checked;
CheckBox3.Enabled := not CheckBox5.Checked;
CheckBox4.Enabled := not CheckBox5.Checked;
end;
//=============================================================================
// APathで指定するフォルダ内(サブフォルダも含む)の全てのファイルを検索して
// ListView1に表示する(ファイル名のみ)
// サブアイテムに属性の頭文字を表示
// ここではWin32APIのFindFirstFileとFindNextFileを使ってみた
//=============================================================================
procedure TForm1.GetFilesListAll(APath: String);
var
LHandle : THandle;
LFileName : String;
LAttrib : DWORD;
LSearchPath : String;
LItem : TListItem;
LTempStr : String;
LFileData : TWin32FindData;
begin
LHandle := FindFirstFile(PChar(APath + '*.*'), LFileData);
if LHandle <> INVALID_HANDLE_VALUE then begin
repeat
LFileName := LFileData.cFileName;
LAttrib := LFileData.dwFileAttributes;
if not ((LFileName = '..') or (LFileName = '.')) then begin
if LAttrib = FILE_ATTRIBUTE_DIRECTORY then begin
LSearchPath := IncludeTrailingPathDelimiter(APath + LFileName);
//フォルダの場合は,この関数を再帰的に呼出して,そのフォルダ内を検索
GetFilesListAll(LSearchPath);
end else begin
LItem := ListView1.Items.Add;
LItem.Caption := LFileName;
//属性を取得
LTempStr := ' ';
if Bool(LAttrib and FILE_ATTRIBUTE_READONLY) then
LTempStr := LTempStr + 'R ';
if Bool(LAttrib and FILE_ATTRIBUTE_HIDDEN) then
LTempStr := LTempStr + 'H ';
if Bool(LAttrib and FILE_ATTRIBUTE_SYSTEM) then
LTempStr := LTempStr + 'S ';
if Bool(LAttrib and FILE_ATTRIBUTE_ARCHIVE) then
LTempStr := LTempStr + 'A ';
LItem.SubItems.Add(LTempStr);
Inc(FFilesCount);
end;
end;
until FindNextFile(LHandle, LFileData) = False;
Windows.FindClose(LHandle);
end;
end;
//=============================================================================
// APathで指定するフォルダ内(サブフォルダも含めて)の属性を変更するメソッド
//=============================================================================
procedure TForm1.SetFilesListAttrib(APath: String; dmFileAttributes:Cardinal);
var
LSearchPath : String;
LSearchRec : TSearchRec;
begin
if FindFirst(APath + '*.*', faAnyFile, LSearchRec) = 0 then begin
repeat
if not ((LSearchRec.Name = '..') or (LSearchRec.Name = '.')) then begin
LSearchPath := IncludeTrailingPathDelimiter(APath+LSearchRec.Name);
if LSearchRec.Attr = faDirectory then begin
SetFileAttrib(LSearchPath,dmFileAttributes);
//フォルダの場合は,この関数を再帰的に呼出して,そのフォルダ内を検索
SetFilesListAttrib(LSearchPath, dmFileAttributes);
end else begin
SetFileAttrib(LSearchPath, dmFileAttributes);
Inc(FFilesCount);
end;
end;
until FindNext(LSearchRec) <> 0;
FindClose(LSearchRec);
end;
end;
//=============================================================================
// ファイルやフォルダの属性を変更するメソッド
// 属性を変更したら,一度NORMALにしないとFindFirstで検索できなる場合あり
// FileName : 日時を変更するファイルまたはフォルダ名
// dmFileAttributes : 属性
//=============================================================================
procedure TForm1.SetFileAttrib(FileName: String; dmFileAttributes:Cardinal);
var
LHandle : THandle;
begin
if ChangeFileExt(FileName, '') = ChangeFileExt(Application.ExeName, '') then exit;
try
FileName := ExcludeTrailingPathDelimiter(FileName);
LHandle := Windows.CreateFile(Pchar(FileName),
GENERIC_WRITE,
FILE_SHARE_READ,
nil,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
0);
//フォルダの場合は失敗する
//FileHandle <> INVALID_HANDLE_VALUEでないことに注意
if LHandle > 0 then begin
//属性を変更する
SetFileAttributes(PChar(FileName), dmFileAttributes);
end;
finally
CloseHandle(LHandle);
end;
end;
end.
10_指定フォルダ内のファイル一覧 ( TShell オブジェクト使用 ) |
ファイル情報は,TShell オブジェクトを利用しても取得できます.その例です.このテストプログラムでは,TShell オブジェクトをコンポーネントにして Form に配置して利用しています.
TShell オブジェクトのコンポーネントとしてインストールする方法は,[タイプライブラリの取り込み] の記事を参考にしてください.
|
|
図26
設計時画面
|
|
図27
実行結果例
- 指定フォルダ内のファイルリスト
- フォルダ名のリストも含む
- ファイルサイズの計算には少し工夫が必要かも知れない
|
リスト11
指定フォルダ内のファイル一覧 (TShell オブジェクト使用) |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Shell32_TLB, ComCtrls, OleServer;
type
TForm1 = class(TForm)
Shell1: TShell;
Panel1: TPanel;
Button1: TButton;
Panel2: TPanel;
ListView1: TListView;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
FBasePath : String;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
FileCtrl;
{$R *.dfm}
//=============================================================================
// 初期設定
// 選択フォルダの初期値を設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
FBasePath := ExtractFileDir(Application.ExeName);
ListView1.RowSelect := True;
end;
//=============================================================================
// 指定フォルダ内のファイル一覧をListViewに表示
//
// FolderItemのプロパティは以下の通り
// Path : WideString Itemのフルパス
// Name : WideString Itemのファイル名
// Type_ : WideString Itemのタイプ文字列
// Size : Integer Itemのサイズ
// ModifyDate : TDateTiem Itemの最終更新日時
// IsFileSystem : WordBool Itemがファイルシステムかどうか
// IsFolder : WordBool Itemがフォルダかどうか
// GetFolder : IDispatch Itemがフォルダの時,フォルダオブジェクト
// IsLink : WordBool Itemが(*.lnk,*.pif,*.url)ならTrue
// GetLink : ShellLinkObject Itemがショートカットの時,ShellLinkObject
// Parent : IDispatch Itemの親オブジェクト
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LSHFolder : Shell32_TLB.Folder;
LSHFolderItem : Shell32_TLB.FolderItem;
LDateTime : TDateTime;
LValue : WideString;
i : Integer;
begin
//Delphi 2007より前には,最後の引数がない
//Vista以降で FileCtrl.SelectDirectory('フォルダ指定', '', SrcDir, [sdNewUI])
//でダイアログを表示すると,指定したフォルダ位置までスクロールしてくれない
if SelectDirectory('フォルダ選択', '', FBasePath, []) then begin
ListView1.Items.Clear;
ListView1.Update;
ListView1.Items.BeginUpdate;
LSHFolder := Shell1.NameSpace(FBasePath);
//SHFolderオブジェクトの各アイテム(ファイル)の情報取得
for i := 0 to LSHFolder.Items.Count - 1 do begin
//FoldetItemオブジェクト(つまりフォルダ内の各ファイル)
LSHFolderItem := LSHFolder.Items.Item(i);
//ファイル名
ListView1.Items.Add.Caption := LSHFolderItem.Name;
//サイズ
if LSHFolderItem.IsFolder then begin
ListView1.Items[i].SubItems.Add('');
end else begin
LValue := FormatFloat('###,##0 KB', LSHFolderItem.Size div 1024);
ListView1.Items[i].SubItems.Add(LValue);
end;
//最終更新日時
LDateTime := LSHFolderItem.ModifyDate;
LValue := FormatDateTime('yyyy/mm/dd hh:mm', LDateTime);
ListView1.Items[i].SubItems.Add(LValue);
end;
ListView1.Items.EndUpdate;
end;
end;
end.
11_コンテキストメニューの表示
- Delphi 2007 以前用 |
筆者が作成する業務アプリではほとんど必要性は感じませんが,エクスプローラと同じように,選択したファイルのコンテキストメニューは,シェルの機能を使用すると実現できます.これは,上で述べたシェルオブジェクトではなく,シェルネームスペース (シェル名前空間) のことです.
シェルの機能を使用するのは結構面倒ですので,筆者の得意技で,他の方のコンポーネントを利用することにします.それは,ヒシアマゾンさん作の DRPCOMEX というコンポーネントです.Delphian World にありましたが,現在入手できませんのでこのサンプルのフォルダ内に添付しています.
このコンポーネントは,Delphi 2007 以前用です.したがって,本サンプルは Delphi 2007 以前限定です.以下の結果は,Windows 7 U64(SP1) + Delphi 2007-R2 での実行結果です.
このコンポーネントは,コンテキストメニューを表示しなくても,コンテキストメニューのコマンドを 実行することもできます.
|
|
図28
設計時画面
|
|
図29
実行例
- コンテキストメニュー表示コードは,リストビューの OnMouseDown イベント内
|
リスト12
エクスプローラと同じコンテキストメニューが簡単に実現可能 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls, DRPCOMEX;
type
TForm1 = class(TForm)
Panel1: TPanel;
ListView1: TListView;
ContextMenuEx1: TContextMenuEx;
Panel2: TPanel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure ListView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private 宣言 }
FDirName : String;
procedure GetFilesList(APath: String);
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
FileCtrl;
{$R *.dfm}
//=============================================================================
// 指定フォルダ内のファイルとフォルダを表示
// SelectDirectoryの使用にはusesにFileCtrlが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
FDirName := ExtractFileDir(Application.ExeName);
//Delphi 2007より前には,最後の引数がない
//Vista以降で FileCtrl.SelectDirectory('フォルダ指定', '', SrcDir, [sdNewUI])
//でダイアログを表示すると,指定したフォルダ位置までスクロールしてくれない
if SelectDirectory('検索フォルダ指定', '', FDirName, []) then begin
GetFilesList(FDirName);
end;
end;
//=============================================================================
// APathで指定するフォルダ内の全てのファイルを検索してListViewに表示
// サブフォルダ内は検索しない
//=============================================================================
procedure TForm1.GetFilesList(APath: String);
var
LFilesCount : Integer;
LSearchPath : String;
LSearchRec : TSearchRec;
begin
Panel1.Caption := '';
LFilesCount := 0;
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
LSearchPath := IncludeTrailingPathDelimiter(APath) + '*.*';
if FindFirst(LSearchPath, faAnyFile, LSearchRec) = 0 then begin
repeat
if not ((LSearchRec.Name = '..') or (LSearchRec.Name = '.')) then begin
ListView1.Items.Add.Caption := LSearchRec.Name;
Inc(LFilesCount);
end;
until FindNext(LSearchRec) <> 0;
FindClose(LSearchRec);
end;
ListView1.Items.EndUpdate;
Panel1.Caption := 'ファイル数 : ' + IntToStr(LFilesCount);
end;
//=============================================================================
// マウスクリック位置のファイルのコンテキストメニューを表示
// FDirName : 表示中のフォルダ名
// ContextMenuEx1 : ヒシアマゾンさん作のコンポーネント
//=============================================================================
procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
i : Integer;
LStrList : TStringList;
LFullPath : String;
begin
if FDirName = '' then exit;
if Button = mbRight then begin
LStrList := TStringList.Create;
LFullPath := IncludeTrailingPathDelimiter(FDirName);
try
if ListView1.SelCount = 0 then begin
LStrList.Add(LFullPath);
end else begin
for i := 0 to ListView1.SelCount - 1 do begin
LStrList.Add(LFullPath + ListView1.Selected.Caption);
end;
end;
ContextMenuEx1.CMFileName.Assign(LStrList);
finally
FreeAndNil(LStrList);
end;
ContextMenuEx1.DoMenuEx(ListView1.Handle, X, Y);
//削除やファイル名変更は,ファイルリストを再取得しないと結果の確認ができない
//タイムラグが必要なようである(程度については不明)
Sleep(100);
GetFilesList(FDirName);
end;
end;
end.
ディスク上のファイルサイズを取得するサンプルです.この値は,[ファイルのプロパティ] のダイアログで [ディスク上のサイズ] として表示される値のことです.
stackoverflow に掲載されているコードをひな型として利用しています.ただし,ファイルサイズの値の変数は,符号なしの 64 ビット整数型に変更しています.Cardinal 型のままだと,32 ビット以上のファイルサイズの値が正しく取得できません.
|
ディスク上のファイルサイズはクラスタ単位です.対象のディスクのクラスタサイズを知る必要があります.本サンプルでは
GetDiskFreeSpace 関数を使用して取得しています.
次にファイルサイズを取得します.そして,ファイルサイズの値とクラスタサイズの値からディスク上のサイズを計算します.
本サンプルでは,ファイルサイズの取得に GetCompressedFileSize 関数を使用しています.この関数で圧縮属性のファイルサイズを取得すると,圧縮属性のファイルのファイルサイズとディスク上のサイズは同じ圧縮時の値となります.非圧縮属性時のファイルサイズが必要な場合は,他の関数でファイルサイズを取得します.
|
|
図30
4,096 バイトのファイルの例
|
|
図31
4,097 バイトのファイルの例
- 上の図よりも 1 バイト多いだけだか,1 クラスタのサイズである 4,096 を超えている
- したがって,ディスク上のサイズは 2 クラスタ分となる
|
|
図32
約 100 GB のバイナリファイルの例 |
リスト13
ファイルのディスク上のサイズを取得するサンプル |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
OpenDialog1: TOpenDialog;
LabeledEdit1: TLabeledEdit;
LabeledEdit2: TLabeledEdit;
LabeledEdit3: TLabeledEdit;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//-----------------------------------------------------------------------------
// 指定ファイルのサイズとディスク上のサイズを取得するルーチン
//-----------------------------------------------------------------------------
procedure GetFileSizeOnDisk(const FileName: string; out AFileSize, ASizeOnDisk: UInt64);
var
LDriveLetter : string;
LSectorsPerCluster : DWORD;
LBytesPerSector : DWORD;
LDummy : DWORD;
LClusterSize : DWORD;
LFileSizeHigh : UInt64;
LFileSizeLow : UInt64;
begin
AFileSize := 0;
ASizeOnDisk := 0;
//ファイルが存在しない場合
if not FileExists(FileName) then begin
exit;
end;
//ドライブレターを取り出す(ex. d:\)
LDriveLetter := IncludeTrailingPathDelimiter(ExtractFileDrive(FileName));
//該当ディスクの(セクタ数/クラスタ)と(バイト数/セクタ)を取得
if not GetDiskFreeSpace(PChar(LDriveLetter),
LSectorsPerCluster,
LBytesPerSector,
LDummy,
LDummy) then begin
//関数の実行に失敗した場合
//エラーの検出はRaiseLastOSError
exit;
end;
//クラスタのサイズを計算
LClusterSize := LSectorsPerCluster * LBytesPerSector;
//ファイルサイズの上位と下位のDWORD値(32ビット)を取得
//上位DWORDは引数から取得.下位DWOODは関数の戻り値から取得
//圧縮属性のファイルの場合は圧縮したファイルサイズとなる
LFileSizeLow := GetCompressedFileSize(PChar(FileName), @LFileSizeHigh);
//ファイルサイズとディスク上のファイルサイズを計算
if (GetLastError = NO_ERROR) or (LFileSizeLow <> INVALID_FILE_SIZE) then begin
//エラーの検出はRaiseLastOSError
AFileSize := LFileSizeHigh shl 32 + LFileSizeLow;
ASizeOnDisk := AFileSize;
if (ASizeOnDisk mod LClusterSize) > 0 then begin
ASizeOnDisk := ASizeOnDisk + (LClusterSize) - (ASizeOnDisk mod LClusterSize);
end;
end;
end;
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
OpenDialog1.InitialDir := ExtractFileDir(Application.ExeName);
end;
//=============================================================================
// ファイルサイズとディスク上のサイズを取得して表示
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFileName : String;
LFileSize : UInt64;
LFileDiskSize : UInt64;
begin
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
OpenDialog1.InitialDir := ExtractFileDir(OpenDialog1.FileName);
LabeledEdit1.Text := '';
LabeledEdit2.Text := '';
LabeledEdit3.Text := '';
//選択したファイル名
LFileName := OpenDialog1.FileName;
LabeledEdit1.Text := LFileName;
LabeledEdit1.SelStart := Length(LabeledEdit1.Text);
//ファイルサイズとディスク上のサイズを取得して表示
GetFileSizeOnDisk(LFileName, LFilesize, LFileDiskSize);
LabeledEdit2.Text := FormatFloat('##,##0 バイト', LFileSize);
LabeledEdit3.Text := FormatFloat('##,##0 バイト', LFileDiskSize);
end;
end.
13_TDateTime 型を使用しないファイルの日時変更と取得 |
上の方のサンプルで,TDateTime 型の値を TFileTime 型,TSystemTime 型等に変換してファイルの日時を取得あるいは変更するサンプルを掲載していますが,参考として,TDateTime 型を使用しないサンプルを掲載しておきます.
上の方のサンプルとの違いは,取得の際に SystemTimeToDateTime 関数を使用しないことと,タイムスタンプの変更の際に DateTimeToSystemTime 関数を使用していないことです.
本サンプルでは,ファイルの更新日時だけを変更,または取得します.
|
|
図33
設計時画面 |
|
図34
実行結果 |
リスト14
TDateTime 型を使用しないファイルの日時変更と取得 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
OpenDialog1: TOpenDialog;
LabeledEdit1: TLabeledEdit;
LabeledEdit2: TLabeledEdit;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
OpenDialog1.InitialDir := ExtractFileDir(Application.ExeName);
end;
//=============================================================================
// ファイルの日付時刻を年月日時分秒,ミリ秒を個別に設定する例
// TDateTime型を使用しない方法
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFileName : string;
LModifyTime : TSystemTime;
LFileTime : TFileTime;
LWriteFileTime : TFileTime;
LFileHandle : THandle;
begin
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
OpenDialog1.InitialDir := ExtractFileDir(OpenDialog1.FileName);
LabeledEdit1.Text := OpenDialog1.FileName;
LabeledEdit1.SelStart := Length(LabeledEdit1.Text);
LabeledEdit2.Text := '';
//対象のファイルのフルパス
LFileName := Trim(LabeledEdit1.Text);
//現在の日付と時刻に設定変更する場合
//現在の日付時刻をTSystemTime型で取得
GetLocalTime(LModifyTime);
//個別に設定する場合は以下のようにTSystemTimeの各メンバに値をセットする
LModifyTime.wYear := 2016;
LModifyTime.wMonth := 7;
LModifyTime.wDay := 19;
LModifyTime.wHour := 16;
LModifyTime.wMinute := 10;
LModifyTime.wSecond := 20;
LModifyTime.wMilliseconds := 300;
//SystemTimeをローカルのFileTimeに変換
SystemTimeToFileTime(LModifyTime, LFileTime);
//ローカルの日時をGMT(世界協定時刻)に変換
LocalFileTimeToFileTime(LFileTime, LWriteFileTime);
//FileOpen関数は内部ではCreateFile関数で処理している
LFileHandle := FileOpen(LFileName, fmOpenReadWrite);
try
//タイムスタンプを変更
SetFileTime(LFileHandle, nil, nil, @LWriteFileTime);
finally
FileClose(LFileHandle);
end;
//確認表示
Button2Click(nil);
end;
//=============================================================================
// ファイルの日付時刻を年月日時分秒,ミリ秒を個別に取得する例
// TDateTime型を使用しない方法
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LFileName : string;
LFileHandle : THandle;
LModifyTime : TFileTime;
LTempTime : TFileTime;
LSystemTime : TSystemTime;
LYear : Word;
LMonth : Word;
LDay : Word;
LHour : Word;
LMinute : Word;
LSecond : Word;
LMilliseconds : Word;
LFormatText : string;
begin
if Sender <> nil then begin
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
OpenDialog1.InitialDir := ExtractFileDir(OpenDialog1.FileName);
LabeledEdit1.Text := OpenDialog1.FileName;
LabeledEdit1.SelStart := Length(LabeledEdit1.Text);
end;
LabeledEdit2.Text := '';
//対象のファイルのフルパス
LFileName := Trim(LabeledEdit1.Text);
//FileOpen関数は内部ではCreateFile関数で処理している
LFileHandle := FileOpen(LFileName, fmOpenRead);
try
// タイムスタンプを取得
GetFileTime(LFileHandle, nil, nil, @LModifyTime);
finally
FileClose(LFileHandle);
end;
//FileTime形式(世界協定時刻)を地域に合わせる
FileTimeToLocalFileTime(LModifyTime, LTempTime);
//FileTime形式をSystemTime形式にする
FileTimeToSystemTime(LTempTime, LSystemTime);
LFormatText := '%4d年%2d月%2d日 %2d時%2d分%2d秒%3d';
LYear := LSystemTime.wYear;
LMonth := LSystemTime.wMonth;
LDay := LSystemTime.wDay;
LHour := LSystemTime.wHour;
LMinute := LSystemTime.wMinute;
LSecond := LSystemTime.wSecond;
LMilliseconds := LSystemTime.wMilliseconds;
LabeledEdit2.Text := Format(LFormatText,
[LYear, LMonth, LDay, LHour, LMinute, LSecond, LMilliseconds]);
end;
//=============================================================================
// ファイルの日付時刻を年月日時分秒,ミリ秒を個別に取得する例
// TDateTime型を使用する方法
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
LFileName : string;
LFileHandle : THandle;
LModifyTime : TFileTime;
LTempTime : TFileTime;
LSystemTime : TSystemTime;
LYear : Word;
LMonth : Word;
LDay : Word;
LHour : Word;
LMinute : Word;
LSecond : Word;
LMilliseconds : Word;
LFormatText : string;
LDataTime : TDateTime;
begin
if Sender <> nil then begin
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
OpenDialog1.InitialDir := ExtractFileDir(OpenDialog1.FileName);
LabeledEdit1.Text := OpenDialog1.FileName;
LabeledEdit1.SelStart := Length(LabeledEdit1.Text);
end;
LabeledEdit2.Text := '';
//対象のファイルのフルパス
LFileName := Trim(LabeledEdit1.Text);
//FileOpen関数は内部ではCreateFile関数で処理している
LFileHandle := FileOpen(LFileName, fmOpenRead);
try
// タイムスタンプを取得
GetFileTime(LFileHandle, nil, nil, @LModifyTime);
finally
FileClose(LFileHandle);
end;
//FileTime形式(世界協定時刻)を地域に合わせる
FileTimeToLocalFileTime(LModifyTime, LTempTime);
//FileTime形式をSystemTime形式にする
FileTimeToSystemTime(LTempTime, LSystemTime);
//SystemTime形式をDelphiのTDateTime形式に変換
LDataTime := SystemTimeToDateTime(LSystemTime);
DecodeDate(LDataTime, LYear, LMonth, LDay);
DecodeTime(LDataTime, LHour, LMinute, LSecond, LMilliseconds);
LFormatText := '%4d年%2d月%2d日 %2d時%2d分%2d秒%3d';
LabeledEdit2.Text := Format(LFormatText,
[LYear, LMonth, LDay, LHour, LMinute, LSecond, LMilliseconds]);
end;
end.
14_IOUtils.TFile を使用したファイルの日時変更と取得 |
Delphi 2010 で実装された TFile のメソッド類を使用すると,簡単にファイルの日時の取得や変更ができます.そのサンプルです.
ディレクトリだけの場合は,IOUtils.TDirectory に同じ名前のメソッドがあります.TDirectory の関数を使用すると,ディレクトリ内のファイルのタイムスタンプは元のままで,ディレクトリだけのタイムスタンプを変更できます.
本サンプルでは,ファイルの更新日時だけを変更,または取得します.
|
|
図35
実行結果
- TDateTime 型の値を,以下の方法で文字列にして表示
(1) DateTimeToString
(2) FormatDateTime
(3) 年,月,日,時,分,秒,ミリ秒に分解
- 結果は全て同じ
|
リスト15
IOUtils.TFile を使用したファイルの日時変更と取得 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button2: TButton;
Button1: TButton;
OpenDialog1: TOpenDialog;
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
protected
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
DateUtils,
IOUtils;
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
OpenDialog1.InitialDir := ExtractFileDir(Application.ExeName);
end;
//=============================================================================
// ファイルのタイムスタンプ(更新日時)の設定
// IOUtils.TFileを使用する例
//
// usesにDateUtils,IOUtilsが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFilePath : String;
LModifyTime : TDateTime;
LYear : Word;
LMonth : Word;
LDay : Word;
LHour : Word;
LMinute : Word;
LSecond : Word;
LMilliseconds : Word;
begin
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
OpenDialog1.InitialDir := ExtractFileDir(OpenDialog1.FileName);
LFilePath := OpenDialog1.FileName;
LYear := 2016;
LMonth := 7;
LDay := 19;
LHour := 16;
LMinute := 10;
LSecond := 20;
LMilliseconds := 50;
//年月日と時刻の各要素の値を元にしてTDataTime型の変数に変換
LModifyTime := EncodeDateTime(LYear, LMonth, LDay,
LHour, LMinute, LSecond, LMilliseconds);
//ファイルの更新日時(最終書き込み日時)を変更
IOUtils.TFile.SetLastWriteTime(LFilePath, LModifyTime);
//確認表示
Button2Click(nil);
end;
//=============================================================================
// ファイルのタイムスタンプ(更新日時)の取得
// IOUtils.TFileを使用する例
//
// usesにDateUtils,IOUtilsが必要
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LFilePath : String;
LModifyTime : TDateTime;
LYear : Word;
LMonth : Word;
LDay : Word;
LHour : Word;
LMinute : Word;
LSecond : Word;
LMilliseconds : Word;
LText : string;
begin
if Sender <> nil then begin
OpenDialog1.OptionsEx := [];
OpenDialog1.FileName := '';
if not OpenDialog1.Execute then exit;
OpenDialog1.InitialDir := ExtractFileDir(OpenDialog1.FileName);
end;
LFilePath := OpenDialog1.FileName;
//ファイルの更新日時(最終書き込み日時)を取得
LModifyTime := IOUtils.TFile.GetLastWriteTime(LFilePath);
//取得した日付時刻の値を書式設定した文字列にする
//いくつかの書式設定をやってみる
DateTimeToString(LText, 'yyyy年mm月dd日 hh時nn分ss秒zzz', LModifyTime);
LText := LText + sLineBreak
+ FormatDateTime('yyyy年mm月dd日 hh時nn分ss秒zzz', LModifyTime);
//年月日と時刻の各要素に分解して,それらの書式を個別に設定
DecodeDate(LModifyTime, LYear, LMonth, LDay);
DecodeTime(LModifyTime, LHour, LMinute, LSecond, LMilliseconds);
LText := LText + sLineBreak
+ Format('%4d年%.2d月%.2d日 %.2d時%.2d分%.2d秒%.3d',
[LYear, LMonth, LDay, LHour, LMinute, LSecond, LMilliseconds]);
//結果を表示
MessageBox(Handle, PChar(LText), '結果', MB_ICONINFORMATION);
end;
end.
|