山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他ファイル・フォルダーの更新日時を変更
概要
ファイル・フォルダーの日時を変更するサンプルプログラムを作成しました。
このプログラムは更新日はそのままで時刻を0時0分0秒の日時を作成し、ファイルの作成日時,更新日時,アクセス日時を変更します。
以下に実行例を示します。
コマンドラインベースのプログラムですが、プログラムファイル(mtouch2.exe)又はプログラムファイルのショートカットに変更したいファイル・フォルダーをドラックすれば変更できます。
また複数ファイルにも対応しています。
このプログラムは更新日はそのままで時刻を0時0分0秒の日時を作成し、ファイルの作成日時,更新日時,アクセス日時を変更します。
以下に実行例を示します。
D:\flower\IMG_2422.JPG 2018/11/26 20:01:56 2018/11/26 20:01:56 2018/05/25 13:18:40 Chg 2018/05/25 00:00:00 Returnキーを押すと終了します。上の実行例は、1行目がファイル名、2行目が左から変更前の作成日時・アクセス日時・更新日時、3行目が変更後の日時です。
コマンドラインベースのプログラムですが、プログラムファイル(mtouch2.exe)又はプログラムファイルのショートカットに変更したいファイル・フォルダーをドラックすれば変更できます。
また複数ファイルにも対応しています。
テスト環境
コンパイラ
Visual C++ 2008/2013 Express 32bit/64bit マルチバイト/UNICODE実行環境
Windows 10 Home Version 1803 64bitプログラムソースの概要
_tmain
Windowsから最初に呼び出される関数です。日本語が正しく表示できるように_tsetlocal関数を呼び出します。
コマンドライン引数のファイル名がダブルコーテーションで括られている時は削除します。
_putts関数でファイル名を表示します。
file_time_touch関数でファイルの時刻を0時0分0秒に変更します。
file_time_touch
日時を修正するためにCreateFile APIでファイル・フォルダーのハンドルを取得する必要があります。フォルダーのハンドルを取得する場合、CreateFile APIの第6引数にFILE_FLAG_BACKUP_SEMANTICSを指定しないとエラーが発生します。
まず、GetFileAttribute APIで属性を取得します。
属性がディレクトリ(FILE_ATTRBUTE_DIRECTORY属性が有効)の場合はCreateFile APIの第6引数にFILE_FLAG_BACKUP_SEMANTICSを、ファイルの場合はFILE_ATTRIBUTE_NOMALを設定します。
ファイル・フォルダーの日時を取得する。
GetFileTime APIでファイルの作成日時・アクセス日時・更新日時を取得します。GetFileTime APIで取得できる日時はファイルタイムと呼ばれるもので1601年(関ヶ原の戦いの年)1月1日から100n秒(0.1μ秒=10-7秒)で表される64bitの整数です。
まず取得された日時は協定世界時(UTC)ですのでFileTimeToLocalFileTime APIで日本時刻(64bit整数)に変換します。(9時間を加算)
FileTimeToSystemTime APIによりローカルタイム{日本時刻(64bit整数)}を年月日・時分秒が分解されて扱いやすいSYSTEMTIME構造体に変換します。
以下にminwinbase.hで定義されているSYSTEMTIME構造体を示します。
typedef struct _SYSTEMTIME {
WORD wYear; // 西暦
WORD wMonth; // 月
WORD wDayOfWeek // 曜日 日曜=0 土曜=6
WORD wDay; // 日
WORD wHour; // 時
WORD wMinute; // 分
WORD wSecond; // 秒
WORD wMilliseconds; // ミリ秒
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
SYSTEMTIME構造体では年月日や時分秒がメンバーとなっていますので_tprintf関数で作成日時・アクセス日時・更新日時を標準出力に表示します。ファイル・フォルダーの日時を変更する。
SYSTEMTIME構造体の時分秒のメンバーを0に代入します。日時の取得と逆の順番で日時を変換します。
SYSTEMTIME構造体をSystemTimeToFileTime APIでファイルタイム{ローカルタイム 64bit整数}に変換します。
ローカルタイムをLocalFileTimeToFileTime APIでUTCのファイルタイムに変換します。
SYSTEMTIME構造体では年月日や時分秒がメンバーとなっていますので変更結果を_tprintf関数で標準出力に表示します。
SetFileTime APIでファイル・フォルダーの日時を変更します。
CloseHandle APIでファイル・フォルダーを閉じます。
ソースコード
// 指定されたファイル・フォルダーの時刻を00:00:00に変更する。
// Visual C++ 2008/2013 コマンドライン用
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <time.h>
#include <locale.h>
int file_time_touch(TCHAR* file_name); // 指定されたファイル時刻を変更する
int _tmain(int argc, TCHAR** argv){
_tsetlocale(LC_ALL, _TEXT("")); // UNICODE文字を標準出力に正しく表示できるように
TCHAR* pass;
if (argc == 1){
_putts(_TEXT("使い方\nmtouch2 ファイル名またはフォルダー名"));
return 1;
}
for (int n = 1; n < argc; n++){
pass = argv[n];
if (pass[0] == _T('\"')){
size_t len = _tcslen(pass);
if (pass[len - 1] == _T('\"'))
pass[len - 1] = _T('\0');
++pass;
}
_putts(pass);
file_time_touch(pass);
}
_putts(_TEXT("Returnキーを押すと終了します。"));
getchar();
return 0;
}
// 指定されたファイルの日付を変更する
int file_time_touch(TCHAR* file_name){
HANDLE hFile;
DWORD attr = GetFileAttributes(file_name);
hFile = CreateFile(file_name, GENERIC_WRITE, 0, 0, OPEN_ALWAYS,
(attr & FILE_ATTRIBUTE_DIRECTORY) ? FILE_FLAG_BACKUP_SEMANTICS : FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE){
_putts(_TEXT("File Open Error"));
return -1;
}
FILETIME CreationTime;
FILETIME AccessTime;
FILETIME WriteTime;
FILETIME localTime;
FILETIME WriteTime2;
SYSTEMTIME systemTime;
// 現在のファイルの日時を取得表示
GetFileTime(hFile,&CreationTime,&AccessTime,&WriteTime);
FileTimeToLocalFileTime(&CreationTime,&localTime); // UTC→ローカルタイム
FileTimeToSystemTime(&localTime,&systemTime); // FILETIMEをSYSTEMTIMEに変換
_tprintf(_TEXT("\t%i/%0.2i/%0.2i %0.2i:%0.2i:%0.2i"),systemTime.wYear,systemTime.wMonth,systemTime.wDay,systemTime.wHour,systemTime.wMinute,systemTime.wSecond);
FileTimeToLocalFileTime(&AccessTime,&localTime); // UTC→ローカルタイム
FileTimeToSystemTime(&localTime,&systemTime); // FILETIMEをSYSTEMTIMEに変換
_tprintf(_TEXT("\t%i/%0.2i/%0.2i %0.2i:%0.2i:%0.2i"),systemTime.wYear,systemTime.wMonth,systemTime.wDay,systemTime.wHour,systemTime.wMinute,systemTime.wSecond);
FileTimeToLocalFileTime(&WriteTime, &localTime); // UTC→ローカルタイム
FileTimeToSystemTime(&localTime, &systemTime); // FILETIMEをSYSTEMTIMEに変換
_tprintf(_TEXT("\t%i/%0.2i/%0.2i %0.2i:%0.2i:%0.2i\n"), systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
// 時刻のみ00:00:00にする
systemTime.wHour = 0;
systemTime.wMinute = 0;
systemTime.wSecond = 0;
// ファイルの日時の変更
SystemTimeToFileTime(&systemTime, &localTime); // SYSTEMTIMEをFILETIMEに変換
LocalFileTimeToFileTime(&localTime, &WriteTime2); // ローカルタイム→UTC
_tprintf(_TEXT("Chg\t%i/%0.2i/%0.2i %0.2i:%0.2i:%0.2i\n"), systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
if(SetFileTime(hFile,&WriteTime2,&WriteTime2,&WriteTime2)==0){
_putts(_TEXT("\tSetFileTime API error"));
CloseHandle(hFile);
return -2;
}
CloseHandle(hFile);
return 0;
}
Copyright (C) 2012 山本ワールド All Rights Reserved.