>> WINAPI入門トップに戻る

ファイルの作成、削除

今回はファイルの作成、削除、コピー、移動について説明します。

ファイルの作成については、CreateFile関数を使います。

HANDLE CreateFile(
LPCTSTR lpFileName, // ファイル名
DWORD dwDesiredAccess, // アクセスモード
DWORD dwShareMode, // 共有モード
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // セキュリティ記述子
DWORD dwCreationDisposition, // 作成方法
DWORD dwFlagsAndAttributes, // ファイル属性
HANDLE hTemplateFile // テンプレートファイルのハンドル
);

第二引数には、ファイルを読み込むのか書き込むかを示す定数を指定します。

0	オブジェクトへのデバイス問い合わせアクセスを指定します。アプリケーションは、デバイスにアクセスすることなく、デバイス属性の問い合わせを行えます。
GENERIC_READ	オブジェクトへの読み取りアクセスを指定します。データの読み取りとファイルポインタの移動ができます。読み書きアクセスを行うには、GENERIC_WRITE と共に指定します。
GENERIC_WRITE	オブジェクトへの書き込みアクセスを指定します。データの書き込みとファイルポインタの移動ができます。読み書きアクセスを行うには、GENERIC_READ と共に指定します。


読み込むならGENERIC_READ、書き込む(ファイル作成)ならGENERIC_WRITEを指定します。
第三引数は共有モードを指定します。定数は以下のものがあります。

0	共有不可
FILE_SHARE_DELETE	Windows NT/2000:これ以降、オブジェクトを開こうとしたときに削除アクセスを要求した場合のみ、その操作を許可します。
FILE_SHARE_READ	これ以降、オブジェクトを開こうとしたときに読み取りアクセスを要求した場合のみ、その操作を許可します。
FILE_SHARE_WRITE	これ以降、オブジェクトを開こうとしたときに書き込みアクセスを要求した場合のみ、その操作を許可します。


書いてあるとおりですが、共有したくないときは0を指定します。
第三引数はNULLを指定すればデフォルトのセキュリティ識別子が使われます。
第四引数は作成方法を指定します。以下のものがあります。

CREATE_NEW	新しいファイルを作成します。指定したファイルが既に存在している場合、この関数は失敗します。
CREATE_ALWAYS	新しいファイルを作成します。指定したファイルが既に存在している場合、そのファイルを上書きし、既存の属性を消去します。
OPEN_EXISTING	ファイルを開きます。指定したファイルが存在していない場合、この関数は失敗します。
デバイスに対して CreateFile 関数を呼び出す際に OPEN_EXISTING フラグを使うべき状況については、この関数の「解説」を参照してください。
OPEN_ALWAYS	ファイルが存在している場合、そのファイルを開きます。指定したファイルが存在していない場合、この関数は dwCreationDisposition パラメータで CREATE_NEW が指定されていたと仮定して新しいファイルを作成します。
TRUNCATE_EXISTING	ファイルを開き、ファイルのサイズを 0 バイトにします。呼び出し側プロセスは、dwDesiredAccess パラメータで、少なくとも GENERIC_WRITE アクセス権を指定しなければなりません。指定したファイルが存在していない場合、この関数は失敗します。


このCreateFile関数はファイルを読み込む際にも使いますので、読み込み用の定数もいくつかあります。
説明は記述の通りです。

第5引数はファイルの属性です。隠しファイルとかアーカイブファイルとかを指定します。以下のものがあります。

FILE_ATTRIBUTE_ARCHIVE	このファイルをアーカイブするべきです。アプリケーションはこの属性を、ファイルのバックアップや削除のためのマークとして使います。
FILE_ATTRIBUTE_ENCRYPTED	このファイルまたはディレクトリを暗号化するよう指示します。ファイルに対して指定した場合、そのファイル内のすべてのデータを暗号化することを意味します。ディレクトリに対して指示した場合、その中に新しく作成されるファイルとサブディレクトリに対して、既定で暗号化を行うことを意味します。
FILE_ATTRIBUTE_SYSTEM と共に指定すると、FILE_ATTRIBUTE_ENCRYPTED フラグは無効になります。
FILE_ATTRIBUTE_HIDDEN	このファイルは隠しファイルです。通常のディレクトリリスティングでは表示されません。
FILE_ATTRIBUTE_NORMAL	このファイルに特に属性を設定しません。単独で指定した場合にのみ、この属性は有効です。
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED	Windows 2000:このファイルを、「インデックスサービス」の対象にしません。
FILE_ATTRIBUTE_OFFLINE	Windows 2000:このファイルのデータは、すぐには利用できません。この属性は、このファイルのデータがオフライン記憶装置へ物理的に移動されたことを示します。この属性は、Windows 2000 の階層記憶管理ソフトウェアである「リモート記憶域」が利用するものです。アプリケーションは、任意にこの属性を変更するべきではありません。
FILE_ATTRIBUTE_READONLY	このファイルは読み取り専用です。アプリケーションはこのファイルの読み取りを行えますが、書き込みや削除はできません。
FILE_ATTRIBUTE_SYSTEM	このファイルは、オペレーティングシステムの一部、またはオペレーティングシステム専用のファイルです。
FILE_ATTRIBUTE_TEMPORARY	このファイルは、一時ファイルとして使われています。ファイルシステムは、データをハードディスクのような大容量記憶装置へ書き込む代わりに、高速なアクセスが行えるよう、すべてのデータをメモリ内に維持することを試みます。アプリケーションは、必要がなくなった段階で一時ファイルをすぐに削除するべきです。


通常のファイルを作成するなら、FILE_ATTRIBUTE_NORMALを指定します。

第6引数はテンプレートファイルを指定します。
作成するファイルに属性と拡張属性を指定するためのものですが、
第5引数で属性はしており、拡張属性も特に指定するものがないのでほぼNULLで構いません。

成功するとHANDLE型のファイルハンドルが返ります。
失敗するとINVALID_HANDLE_VALUEが返ります。

作成して得られたハンドルが必要なくなったら、CloseHandle関数で破棄します。

以下がファイルを作成するサンプルになります。

#include <windows.h>
#include <stdio.h>

#define MSG(m) {\
	MessageBoxA(NULL,m,NULL,MB_OK);}

//ウィンドウハンドル
HWND hwnd;
//インスタンスハンドル
HINSTANCE hinst;

//ウィンドウ横幅
#define WIDTH 500
#define HEIGHT 300



LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)
{
	char buf[1000];
	
	static HANDLE h;


	switch(msg){
		case WM_DESTROY:

			PostQuitMessage(0);
			return 0;

		case WM_LBUTTONDOWN:

			h = CreateFile("test.txt",GENERIC_WRITE,0,NULL,
				CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);

			if(h!=INVALID_HANDLE_VALUE){
				MSG("ファイル作成に成功しました");
				//ハンドルは必要なくなったら閉じる。
				CloseHandle(h);
			}else{
				MSG("ファイル作成に失敗しました");
			}


			return 0;

		
	}
	return DefWindowProc(hwnd,msg,wp,lp);
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
	MSG msg;
	WNDCLASS wc;

	wc.style=CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc=WinProc;
	wc.cbClsExtra=wc.cbWndExtra=0;
	wc.hInstance=hInstance;
	wc.hCursor=wc.hIcon=NULL;
	wc.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszClassName="test";
	wc.lpszMenuName=NULL;
	
	if(!RegisterClass(&wc)){
		MSG("クラスの登録失敗");
		return -1;
	}

	
	//インスタンスハンドル
	hinst=hInstance;

	hwnd=CreateWindowA("test","テストウィンドウ",WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
		0,0,400,400,NULL,NULL,hInstance,NULL);


	if(hwnd==NULL){
		MSG("ウィンドウ作成失敗");
		return -1;
	}


	//エラーチェック用変数
	int check;

	while(check=GetMessage(&msg,NULL,0,0)){
		if(check==-1){
			break;
		}
		DispatchMessage(&msg);
	}

	//クラス解放
	UnregisterClass("test",hinst);

	return 0;

}

これを実行して左クリックをすると、
プロジェクトファイルがあるフォルダと同じフォルダ(カレントディレクトリ)に
「test.txt」というファイルが作成されます。
CREATE_NEWを指定しているので、同名のファイルがあった場合は関数が失敗します。
そのため、2回目以上クリックすると「ファイルの作成に失敗しました」と表示されます。
CREATE_ALWAYSを指定すると、上書きされるようになります。

続いてファイルの削除については、DeleteFile関数を使います。

BOOL DeleteFile(
LPCTSTR lpFileName // ファイル名
);

引数にはただファイル名を指定するだけです。
削除するファイルが存在しないとエラーになり、0が返ります。

以下のコードはファイルを作成して、すぐ削除するコードです。

#include <windows.h>
#include <stdio.h>

#define MSG(m) {\
	MessageBoxA(NULL,m,NULL,MB_OK);}

//ウィンドウハンドル
HWND hwnd;
//インスタンスハンドル
HINSTANCE hinst;

//ウィンドウ横幅
#define WIDTH 500
#define HEIGHT 300



LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)
{
	char buf[1000];
	
	static HANDLE h;


	switch(msg){
		case WM_DESTROY:

			PostQuitMessage(0);
			return 0;

		case WM_LBUTTONDOWN:

			h = CreateFile("test.txt",GENERIC_WRITE,0,NULL,
				CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

			if(h!=INVALID_HANDLE_VALUE){
				MSG("ファイル作成に成功しました");

				//ハンドルは必要なくなったら閉じる。
				CloseHandle(h);

				if(DeleteFile("test.txt")){
					MSG("ファイル削除成功")

				}else{

					MSG("ファイル削除失敗");

				}
			}else{
				MSG("ファイル作成に失敗しました");
			}


			return 0;

		
	}
	return DefWindowProc(hwnd,msg,wp,lp);
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
	MSG msg;
	WNDCLASS wc;

	wc.style=CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc=WinProc;
	wc.cbClsExtra=wc.cbWndExtra=0;
	wc.hInstance=hInstance;
	wc.hCursor=wc.hIcon=NULL;
	wc.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszClassName="test";
	wc.lpszMenuName=NULL;
	
	if(!RegisterClass(&wc)){
		MSG("クラスの登録失敗");
		return -1;
	}

	
	//インスタンスハンドル
	hinst=hInstance;

	hwnd=CreateWindowA("test","テストウィンドウ",WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
		0,0,400,400,NULL,NULL,hInstance,NULL);


	if(hwnd==NULL){
		MSG("ウィンドウ作成失敗");
		return -1;
	}


	//エラーチェック用変数
	int check;

	while(check=GetMessage(&msg,NULL,0,0)){
		if(check==-1){
			break;
		}
		DispatchMessage(&msg);
	}

	//クラス解放
	UnregisterClass("test",hinst);

	return 0;

}


コレを実行すると、
「ファイルの作成に成功しました」というメッセージが出たあと「ファイルの削除に成功しました」という
メッセージが出力されます。
それぞれメッセージどおり、ファイルを作成してすぐ削除しています。

今回の説明は以上です。
次回はファイルのコピー、移動について説明します。


>> 【ファイルのコピー、移動】に進む
>> WINAPI入門トップに戻る