'CFileFind'에 해당되는 글 2건

  1. 2008.02.19 CFileFind에서 MAX_PATH 관련 버그... 6
  2. 2006.08.24 CFileFind 이용 파일 정보 얻기...

2008년 2월호 마이크로소프트웨어 책을 보다가 "CFileFind 안에 진짜 MAX_PATH 버그" 라는 권용휘님의 기사를 보게되었다.

CFileFind 클래스를 종종 이용하기 때문에 기사를 유심히 봤는데 문제가 되는 부분은 CFileFind 클래스의 FindFile() 멤버함수에서 경로를 설정하는 부분중 MAX_PATH를 사용하는데 해당되는 부분에서 영어인 경우는 문제가 없는데 한글인 경우에 문제가 생긴다는 내용인것 같다.

기사의 내용을 참조해 설명하자면 NTFS와 윈도우 커널자체에서는 유니코드를 사용한다고한다. 즉 윈도우에서 폴더나 파일명을 지정할때는 최대 256자(확장자, '.', null문자 등 포함 최대 260자...)를 지정할 수 있는데, NTFS를 사용하는 경우는 유니코드를 사용하기 때문에 영어, 한글 모두 260자까지 사용가능하다.

이때 문제가 되는 부분이 함수내에서 TCHAR가 사용된 부분인데 MFC에서 문자 집합을 "멀티바이트 문자 집합 사용" 으로 지정을 해 놓으면 TCHAR 부분이 ANSI 상태로 컴파일이 되므로 260바이트로 설정이된다.

그런데 한글의 경우 영어와 달리 문자열이 260자인 경우에 유니코드와 ANSI 문자열 모두 520바이트이다. 영어인 경우는 ANSI 문자열의 경우 260바이트이기 때문에 별다른 문제가 없지만 한글의 경우는 문자열이 길어져서 ANSI 문자열 기준으로 260바이트가 넘는다면 처리과정에서 MAX_PATH의 최대값을 넘어가기 때문에 오류가 발생한다..

즉, 한글로 된 폴더나 파일명의 길이가 ANSI 문자열 기준으로 260바이트가 넘게되는 경우에 오류가 발생하는 문제가 있다.

기사를 보고 직접 테스트했을 때 VisualStudio 2005에서 테스트했는데 기사내용처럼 문제가 생겼었고, 문자 집합을 "유니코드 문자 집합 사용"으로 설정한 경우는 정상작동을 했다.

아래는 마이크로소프트웨어에 있는 권용휘님 기사의 일부와 CFileFind의 FindFile 함수의 일부~.



- 기사 참조 -
마이크로소프트웨어(2008년 2월호) - "CFileFind 안에 진짜 MAX_PATH 버그" (권용휘, http://rodream.net)
(위의 글은 권용휘님께 허락을 받고 포스팅한것입니다. 퍼가시거나 할 경우 권용휘님께 연락을 해보세요...)
Posted by Gungume
,

CFileFind 클래스는 매개변수로 넘겨준 경로의 파일 및 폴더 등의 목록을 얻고 각각의 기본적인 정보를 얻어올 수 있는 클래스이다.

일단 CFileFind 클래스의 객체랑 결과값을 받을 변수를 선언한다.
CFileFind m_fileFinder;
BOOL bWorking;

파일과 폴더의 목록을 얻어올 때 매개변수로 넘겨준 경로부터 시작해서 FindNextFile() 멤버함수를 이용해서 계속 다음 파일로 접근하는 방식으로 코딩을 하면 되는데 보통 while()을 이용해서 무한루프를 사용한다.
이때 탈출조건이 필요하므로 BOOL형 변수가 필요하다.(자세한 것은 아래 소스를 통해서...)

가장 기본적인 사용법은 아래와 같다.
bWorking = m_fileFinder.FindFile("경로");
while (bWorking)
{
    bWorking = m_fileFinder.FindNextFile();
    // 얻어온 파일에 대해서 처리...
}
m_fileFinder.Close();

위의 소스를 설명하면 일단 매개변수로 경로가 들어간다...
예를 들면 "C:\\*.*" 이런식이다...
일단 경로를 표시하기 위해서 '\'가 아닌 '\\'임을 주의해야 되고, 와일드카드를 사용할 수 있으므로 보통 해당 경로내의 모든 목록을 얻고 싶으면 예제와 같이 원하는 경로 끝에 '*.*'를 써주면 된다...
당연히 특정 확장자만 얻고 싶으면 '*.bmp' 이런식으로 경로를 지정해주면 된다....

위의 예처럼 경로를 "C:\\*.*" 이렇게 설정해주면 'C:\' 의 모든 파일과 폴더 목록을 얻어온다....
이때 주의점은 기본 기능만으로는 일단 해당 경로만 접근이 되고 하위경로는 들어가지 않는다는 점(하위경로를 들어가려면 재귀함수 등 필요...)과 파일과 폴더를 따로 구분해서 불러오지는 않는다...(그냥 이름순으로 얻어온다...)

어쨌든 위와 같이 쓰면 FindNextFile() 멤버함수에 의해 지정된 경로의 모든 파일과 폴더의 정보를 얻어올 수 있다...
정보를 얻어오면 CFileFind 객체인 m_fileFinder을 이용해서 원하는 작업을 바로 바로 처리해 줄수 있다...
파일명, 액세스 타임 얻기 등의 작업이 가능한데....CRecordSet 클래스를 이용해서 DB를 처리하는것과 비슷하다...

모든 작업이 끝나고 해당 경로의 마지막 파일까지 접근했다면 FindNextFile() 멤버함수의 리턴값에 의해 while() 반복문을 종료한다...

이 클래스로 처리할 수 있는 대략적인 정보는 해당 파일이나 폴더의 이름, 전체경로, 크기, 최근 수정일 등의 기본적인 정보를 얻을 수 있다.

또한 현재 얻어온 정보가 폴더인지, 시스템파일인지, 읽기전용, 숨김파일 등등의 속성을 알수도 있다....

이런 정보를 얻어올 수 있는 멤버함수를 적절히 사용해서 얻어온 파일 목록에 대한 처리가 가능하다.

Posted by Gungume
,