« クラスのデストラクタについて | トップページ | ディスクの管理を一発で起動する。 »

2005年1月14日 (金)

ファイルサイズの取得

エクスプローラでファイルのプロパティを見ると「サイズ」という項目と「ディスク上のサイズ」という項目がある。
この「ディスク上のサイズ」をとるのは工夫がいる。
以下のような感じ。SetupAPIをつかう。
{
	HDSKSPC	hDiskSpace = SetupCreateDiskSpaceList( NULL, NULL, SPDSL_IGNORE_DISK );
	SetupAddToDiskSpaceList( hDiskSpace, path().c_str(), GetSize( path ), FILEOP_COPY, NULL, NULL );
	LONGLONG	size;
	SetupQuerySpaceRequiredOnDrive( hDiskSpace, path.GetDriveLetter().c_str(), &size, NULL, NULL );
	SetupDestroyDiskSpaceList( hDiskSpace );
}
「サイズ」はGetFileSizeで取得できるように思うが、実際にはこの関数はそれほど性能がよくない。
GetFileSizeを使うにはハンドルが必要でファイルをCreateFileで開かなければならない。
が、たまに非共有モードですでにファイルが開かれていたりするとCreateFileは失敗する。

んじゃぁどうするのかというとFindFile系を使う。以下のような感じ。

{
	const char*	pFolder = "c:\\*";
	const char*	pFileName = "test.txt";
	const char*	pFullPath = "c:\\test.txt";

	WIN32_FIND_DATA findData;
	HANDLE	hFind = FindFirstFile(pFullPath,&findData);
	if( hFind != INVALID_HANDLE_VALUE )
	{
		FindClose( hFind );
		return findData.nFileSizeHigh*MAXDWORD+findData.nFileSizeLow;
	}
	else
	{
		//FindFirstFileではだめなのに、FindNextFileだと見つかる場合がある。ものすっごく謎。
		//アクセス権がないファイルの場合などに起こるみたいな気がする。
		hFind = FindFirstFile( pFolder, &findData );

		for( BOOL result = TRUE; result; result = FindNextFile( hFind, &findData ) )
		{
			if( lstrcmp( pFileName, findData.cFileName ) == 0 )
			{
				FindClose( hFind );
				return findData.nFileSizeHigh*MAXDWORD+findData.nFileSizeLow;
			}
		}
		//なければエラー
		FindClose( hFind );
		assert( !"ファイルが見つかりませんでした。" );
		return 0;
	}
}
ちゃんとやろうとすればするほどコードが長くなるというお話。

|

« クラスのデストラクタについて | トップページ | ディスクの管理を一発で起動する。 »

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



« クラスのデストラクタについて | トップページ | ディスクの管理を一発で起動する。 »