ファイル操作2

ファイル操作1ではファイルの操作にハンドルを使用しましたが、このページで紹介する関数はファイル名(ディレクトリ名)で直接操作します。

ファイルの属性

GetFileAttributes関数

ファイルやフォルダには「読み取り専用」や「隠しファイル」などの属性(ファイル属性)があります。

ファイル属性を取得するにはGetFileAttributes関数を使用します。

DWORD GetFileAttributesW(
 LPCWSTR lpFileName
);
ファイルまたはディレクトリlpFileNameのファイルシステム属性を取得する。

引数はファイル名(ディレクトリ名)です。
(ファイルのハンドルではありません)

戻り値は属性を表す定数の組み合わせです。
特に重要なものは太字で表しています。
関数が失敗した場合はINVALID_FILE_ATTRIBUTESを返します。

定数 説明
FILE_ATTRIBUTE_READONLY 読み取り専用
(ファイルのみ)
FILE_ATTRIBUTE_HIDDEN 隠しファイルまたはディレクトリ
FILE_ATTRIBUTE_SYSTEM システムファイルまたはディレクトリ
FILE_ATTRIBUTE_DIRECTORY ディレクトリである
FILE_ATTRIBUTE_ARCHIVE アーカイブファイルまたはディレクトリ
FILE_ATTRIBUTE_DEVICE システムで予約されている
(使用しない)
FILE_ATTRIBUTE_NORMAL 通常のファイル
(属性なし)
このフラグは他のフラグと組み合わせられない
FILE_ATTRIBUTE_TEMPORARY 一時ファイル
FILE_ATTRIBUTE_SPARSE_FILE スパースファイル
FILE_ATTRIBUTE_REPARSE_POINT ファイルまたはディレクトリは再解析ポイント(リパースポイント)に関連付けられている
(ジャンクション、シンボリックリンク)
FILE_ATTRIBUTE_COMPRESSED 圧縮されたファイルまたはディレクトリ
FILE_ATTRIBUTE_OFFLINE すぐに利用できないオフラインファイル
この値は変更すべきではない
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED インデックスサービスの対象になっていないファイルまたはディレクトリ
FILE_ATTRIBUTE_ENCRYPTED 暗号化されたファイルまたはディレクトリ
FILE_ATTRIBUTE_INTEGRITY_STREAM 整合性のあるディレクトリまたはストリーム
(ReFSボリュームのみ。Windows Server 2012以降)
FILE_ATTRIBUTE_VIRTUAL システムで予約されている
(使用しない)
FILE_ATTRIBUTE_NO_SCRUB_DATA スクラブファイルなし属性
(ReFSボリュームのみ。Windows8、Windows Server 2012以降)

これらの定数の組み合わせが返されますので、特定の属性を持つかどうかはビット演算を使用して判定します。


DWORD attr = GetFileAttributes(L"C:\\a.txt");
if (attr == INVALID_FILE_ATTRIBUTES) {
	//属性取得失敗
}

if (attr & FILE_ATTRIBUTE_READONLY) {
	//読み取り専用
}

if (!(attr & FILE_ATTRIBUTE_READONLY)) {
	//読み取り専用ではない
}

GetFileAttributesEx関数

ファイル属性の取得はGetFileAttributesEx関数を使用することもできます。

BOOL GetFileAttributesExW(
 LPCWSTR lpFileName,
 GET_FILEEX_INFO_LEVELS fInfoLevelId,
 LPVOID lpFileInformation
);
ファイルまたはディレクトリlpFileNameのファイルシステム属性を取得しlpFileInformationに格納する。
成功した場合は0以外を、失敗した場合は0を返す。

第二引数fInfoLevelIdにはGetFileExInfoStandardという定数を指定します。
これは第三引数に格納される値はWIN32_FILE_ATTRIBUTE_DATA構造体である、という意味です。
(この定数以外を指定することはできません)

第三引数lpFileInformationWIN32_FILE_ATTRIBUTE_DATA構造体です。

typedef struct _WIN32_FILE_ATTRIBUTE_DATA {
 DWORD dwFileAttributes;
 FILETIME ftCreationTime;
 FILETIME ftLastAccessTime;
 FILETIME ftLastWriteTime;
 DWORD nFileSizeHigh;
 DWORD nFileSizeLow;
} WIN32_FILE_ATTRIBUTE_DATA, *LPWIN32_FILE_ATTRIBUTE_DATA;
ファイルやディレクトリに関する情報を格納する構造体。

dwFileAttributesメンバはファイルの属性です。
これはGetFileAttributes関数と同様です。

ftCreationTimeftLastAccessTimeftLastWriteTimeメンバはそれぞれ「作成日時」「最終アクセス日時」「更新日時」です。
これはGetFileTime関数で取得されるものと同等です。

nFileSizeHighメンバはファイルサイズの上位DWORD、nFileSizeLowはファイルサイズの下位DWORDです。
これはGetFileSize関数で取得されるものと同等です。
ディレクトリのサイズは取得できません。

GetFileSize関数やGetFileTime関数はファイルハンドルが必要なためファイルのオープンとクローズの処理が必要ですが、GetFileAttributesEx関数はファイル名を指定するだけで情報が取得できます。


WIN32_FILE_ATTRIBUTE_DATA fad;
BOOL b = GetFileAttributesEx(
	L"C:\\a.txt",
	GetFileExInfoStandard,
	&fad);

//ファイル属性
DWORD attr = fad.dwFileAttributes;

SetFileAttributes関数

ファイル属性の設定はSetFileAttributes関数を使用します。

BOOL SetFileAttributesW(
 LPCWSTR lpFileName,
 DWORD dwFileAttributes
);
ファイルまたはディレクトリlpFileNameの属性をdwFileAttributesに設定する。
成功した場合は0以外を、失敗した場合は0を返す。

第二引数に指定する値はGetFileAttributes関数で説明した定数の組み合わせですが、指定できる値は以下のものに制限されています。

  • FILE_ATTRIBUTE_READONLY
  • FILE_ATTRIBUTE_HIDDEN
  • FILE_ATTRIBUTE_SYSTEM
  • FILE_ATTRIBUTE_NORMAL
  • FILE_ATTRIBUTE_TEMPORARY
  • FILE_ATTRIBUTE_OFFLINE
  • FILE_ATTRIBUTE_NOT_CONTENT_INDEXED

DWORD attr = GetFileAttributes(L"C:\\a.txt");
//読み取り専用属性を設定
SetFileAttributesW(L"C:\\a.txt", attr | FILE_ATTRIBUTE_READONLY);

attr = GetFileAttributes(L"R:\\a.txt");
//読み取り専用属性を解除
SetFileAttributesW(L"C:\\a.txt", attr & ~FILE_ATTRIBUTE_READONLY);

ファイルの削除

ファイルの削除はDeleteFile関数を使用します。

BOOL DeleteFile(
 LPCTSTR lpFileName
);
ファイルlpFileNameを削除する。
成功した場合は0以外を、失敗した場合は0を返す。

指定したファイルパスのファイルを削除します。
ファイルが存在しない、読み取り専用、削除権限がない、他のプログラムが使用中、などの場合には関数は失敗します。
また、ごみ箱には移動せず即座に削除されるので注意してください。

ディレクトリの削除にはRemoveDirectory関数を使用します。

ファイルのコピー

ファイルのコピーはCopyFile関数を使用します。

BOOL CopyFile(
 LPCTSTR lpExistingFileName,
 LPCTSTR lpNewFileName,
 BOOL bFailIfExists
);
既存のファイルlpExistingFileNameを新しいファイルlpNewFileNameにコピーする。
成功した場合は0以外を、失敗した場合は0を返す。

第三引数のbFailIfExistsはBOOL値で、コピー先のパスにすでにファイルが存在する場合の動作を決定します。
TRUEを指定するとファイルの上書きはせず関数は失敗します。
FALSEを指定するとファイルを上書きします。

ディレクトリをコピーする関数は標準では用意されていません。
(ディレクトリの移動、名前変更、コピーを参照)

ファイルの移動(名前の変更)

ファイルの移動はMoveFile関数を使用します。

BOOL MoveFile(
 LPCTSTR lpExistingFileName,
 LPCTSTR lpNewFileName
);
ファイルまたはディレクトリlpExistingFileNameをlpNewFileNameに移動する。
成功した場合は0以外を、失敗した場合は0を返す。

移動先にすでにファイルが存在する場合は関数は失敗します。

ファイル名を変更する場合もこの関数を使用します。

この関数はディレクトリの移動も可能です。
ただしディレクトリを移動する場合、異なるボリューム(別ドライブ)への移動はできません。
(ディレクトリの移動、名前変更、コピーを参照)

ファイルの存在確認

指定のファイルが存在するかの確認はPathFileExists関数を使用します。

BOOL PathFileExistsW(
 LPCWSTR pszPath
);
ファイルまたはディレクトリpszPathが存在する場合はTRUEを返す。
存在しない場合はFALSEを返す。

この関数の使用にはShlwapi.hのインクルードおよびShlwapi.libのリンクが必要です。


#pragma comment(lib, "Shlwapi.lib")

#include<Windows.h>
#include<Shlwapi.h>

ファイルの移動やコピーの前に、宛先にファイルが存在するかをチェックする場合に使用できます。

この関数はディレクトリの存在確認も可能です。

ファイルやディレクトリはあらゆるプログラムからアクセスされるため、存在チェックを行った次の瞬間には別のプログラムによって状態が変更されている可能性があるので注意してください。

ファイルとディレクトリの判別

PathFileExists関数は指定のパスが有効なファイルまたはディレクトリの場合にTRUEを返します。
そのままではファイルとディレクトリを判別できないので、PathIsDirectory関数を使用して識別します。
この関数の使用にはShlwapi.hのインクルードおよびShlwapi.libのリンクが必要です。

BOOL PathIsDirectoryW(
 LPCWSTR pszPath
);
ディレクトリpszPathが存在する場合はTRUEを返す。
存在しない場合はFALSEを返す。

WCHAR* path = L"test.txt";

if (PathFileExists(path)) 
{
	if (PathIsDirectory(path))
	{
		//pathはディレクトリ
	}
	else
	{
		//pathはファイル
	}
}
else
{
	//ファイルまたはディレクトリは存在しない
}

その他、GetFileAttributes関数などでファイルの属性を取得して判別することもできます。


DWORD attr = GetFileAttributes(L"C:\\a.txt");
if (attr == INVALID_FILE_ATTRIBUTES) {
	//属性取得失敗
}

if (attr & FILE_ATTRIBUTE_DIRECTORY) {
	//ディレクトリ
}