[MFC/Win32API] ファイル・フォルダの存在チェック

[MFC] CFileFind

指定されたファイル名のファイルが存在する場合にtrueを返す。
ただし、ディレクトリのパスが与えられた場合、ディレクトリが存在してもfalseを返す。

ファイル単体の存在チェック

CFileFind find;
CString filePath = _T("C:\\foo.bar");

if( find.FindFile( filePath ) ){
 // ファイルが存在
}

フォルダ内ファイルの存在チェック

以下の例ではでファイル名の条件を指定。

CFileFind find;
CString dirPath = _T("C:\\foo\\bar");
dirPath += _T("*.txt"); // ファイルの条件

if( find.FindFile( dirPath ) ){
 // while( find.FindNextFile() ) // ※間違い※これだと処理出来るファイルが実際の数より1つ少ない

 bool flag;
 do{
  flag = find.FindNextFile(); 
  // *.txtファイルが存在したときの処理
 }while( flag ); // これなら対象ファイル全てが処理出来る
}

[Win32 API] Path関数

PathFileExists
指定されたパスにファイル、もしくはディレクトリが存在した場合にtrueを返す。
PathIsDirectory
指定されたパスがディレクトリならtrueを返す。

指定されたパスがファイルかディレクトリかで処理を切り分ける場合

CString path = _T("C:\\foo.bar");
if( ::PathFileExists( path ) && !::PathIsDirectory( path ) ){
 // 指定されたパスにファイルが存在、かつディレクトリでない
}else if( ::PathFileExists( path ) ){
 // 指定されたパスがディレクトリである
}

車輪の再発明

FindFirstFileを利用してもファイル・フォルダの存在確認にできるらしい。が、ルートディレクトリは検出できないっぽい。
上記のような関数を知らなかった為こんなものを作ってしまった。PathIsDirectory関数と(たぶんほぼ)等価なはず。

// 引数で与えられたフォルダのパスが存在するかを確認
// param: folderPath(参照渡し): フォルダのパス(最後の\記号はつけない)
// return: true: フォルダが存在 / false: フォルダが存在しない
bool isFolderExist( CString &folderPath ){
 HANDLE hFind;
 WIN32_FIND_DATA FindFileData;

 hFind = ::FindFirstFile( folderPath, &FindFileData );
 if( FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY ){
  // 引数のパスが正しい(フォルダが存在)
  return true;
 }

 // フォルダが存在しなかった場合、もしくはルートディレクトリを指定していた場合
 // ルートディレクトリならfolderPathの長さは2になるはず(C:)など
 if( folderPath.GetLength() == 2 ){
  TCHAR szBuff[125];	// 4*26 + 1
  ::GetLogicalDriveStrings( sizeof(szBuff), szBuff );
  for( int i = 0; i < 125 /* szBuffの配列長 */; i = i+4 ){
   if( szBuff[i] == folderPath.MakeUpper().GetAt(0) &&
    ':' == folderPath.GetAt(1) ){
    // 指定されたルートディレクトリのドライブレターが有効なドライブであった場合
    return true;
   }
  }
 }
 return false;
}

参考URL

[MFC] UnicodeプロジェクトでのWriteString

ファイルの末尾に受け取ったCString文字列を書き込むという関数作成時のメモ。まー、ログを簡単に出力する為の関数です。

bool underwrite( CString& str ){

 CStdioFile file;
 CString filePath = _T(".\\foo.bar");

 // ファイルを書込専用、ほかのプロセスからは書込不可、
 // ファイルがなければ作成し、あればそのファイルを読み込む
 if( file.Open( filePath, CFile::modeWrite | CFile::shareDenyWrite |
   CFile::modeCreate | CFile::modeNoTruncate ) ){
  // ファイルオープン成功

  // ポインタをファイルの末尾に移動
  file.SeekToEnd();
  // 文字列書込
  file.WriteString( str );
  // ファイルを閉じる 
  file.Close();

 }else{
  return false;
 }
 return true;
}

上記のようなプログラムを組んだのだが、どういうわけか上手く日本語が書き込めない。
「0123あいうabc」のような文字列を与えた場合、ファイルに出力されるのは「0123」となってしまう。

原因はWriteStringがロケール依存関数だった為。WriteStringが呼ばれる前に以下を呼んでやる必要がある。

// #include "locale.h"
_tsetlocale( LC_ALL, _T("") ); //システム既定のロケールに設定
_tsetlocale( LC_ALL, _T("japanese") ); //日本語の場合

参考にしたところ