파일 목록을 얻어갈 때, 얻어 갈 파일의 속성으로 주로 확장자를 사용하는 경우가 많다. 즉, 확장자가 jpg 인 것이나 txt 인 것들을 얻어가는 경우처럼. 또는 특정 파일 속성, 가령 FILE_ATTRIBUTE_ARCHIVE와 같은 속성을 검사할 수도 있기는 한데, 어쨌거나 파일의 특성에 대하여 확장자나 이러한 속성만을 사용하여 파일 목록을 얻어간다는 것은 융통성이 없다.
FindFirstFile, FindNextFile 을 사용하여 파일 목록을 얻어 가는 과정을 생각해 보자. 필터에 맞는 파일을 찾아서 무조건 결과에 반환하도록 구현하곤 한다. 그러나 이 때, 각각의 파일 이름을 파라미터로 넘겨서 이 파일을 과연 결과에 포함시킬 것인가 말 것인가를 결정하는 함수를 파라미터로 받는다면 훨씬 편할 것이다. 물론 필터에 맞는 것을 무조건 고르고 싶다면 NULL을 넘겨 주고. 또한, 종종 더이상 파일 목록을 검사하지 않고 종료해야 할 경우도 있으므로 이에 대한 함수 역시 파라미터로 받으면 좋을 것이다. 실제로 나는 이미지 파일이 몇 개 있나를 검사하고, 10개 이상 있으면 더이상 검사하지 않고 종료해야 하는 경우가 있었다.
지금까지의 생각을 코드로 나타내면 다음과 같다.
bool GetFileNameList(
const std::string& root_path,
const std::string& filter,
std::vector<std::string> *dest,
bool (*skip_checker)(const std::string&) ,
bool (*teriminate_checker)(const std::vector<std::string>&)
)
{
std::string path_filter = root_path + "\\" + filter;
WIN32_FIND_DATA fd = { 0 };
HANDLE hSearch = INVALID_HANDLE_VALUE;
bool bFinished = false;
hSearch = FindFirstFile(path_filter.c_str(), &fd);
if(hSearch != INVALID_HANDLE_VALUE){
while(!bFinished){
if(skip_checker != NULL){
if((*skip_checker)(root_path + "\\" + fd.cFileName) == true){
dest->push_back(fd.cFileName);
}
}
else{ //
dest->push_back(fd.cFileName);
}
if(teriminate_checker != NULL){
// [terminate_checker]는 더이상 파일 이름을 가져올 필요가 없을 때
// true를 반환해야 한다.
if((*teriminate_checker)(*dest) == true) break;
}
bFinished = !FindNextFile(hSearch, &fd);
}
}
return true;
}
즉, 함수의 인자로 두 개의 함수 파라미터를 받아서, 하나는 적당한 파일인지 확인하는데 사용하고, 나머지 하나는 더이상 파일 목록을 살펴 볼 필요가 없는지 결정하는데 사용하는 것이다.
만약 확장자가 jpg, gif, png, tiff, tif 인 것을 가져오고 싶다면? 간단하다. 다음과 같이 skip_checker를 작성하고,
bool is_image_file_extension(const std::string& file_name)
{
char ext[10] = "";
_splitpath(file_name.c_str(), NULL, NULL, NULL, ext);
char *valid_ext[] = { "jpg", "gif", "png", "tif", "tiff"};
int i = 0;
for(i = 0; i<5; i++){
if(strcmp(ext, valid_ext[i]) == 0) return true;
}
return false;
}
다음과 같이 호출하면 되는 것이다.
GetFileNameList(root_path, "*", &image_file_name, is_image_file_extension, NULL);
즉, 정해진 확장자에 대해서만 true 를 반환하는 함수를 만들어서 이 함수 포인터를 인자로 넘겨 주면 되는 것이다.
'컴퓨터 > C++_STL' 카테고리의 다른 글
Strict weak ordering (4) | 2010.05.11 |
---|---|
에지(edge) 객체 구현해 보기 (0) | 2010.05.08 |
멤버 함수의 포인터를 배열에 넣는 방법 (0) | 2009.12.27 |
template과 iterator 변수 사용하기 (2) | 2009.12.27 |
main 의 반환값은 어디에 쓰는가 (1) | 2009.12.27 |