파일 정보 가져오는것에 대해 질문있습니다.
아래의 코드를 이용해 파일의 정보(생성 시간, 마지막 접근 시간, 마지막 수정 시간)을 가져옵니다.
void FileInfo::Init() { if (_FileHandle == INVALID_HANDLE_VALUE) { if ((_FileHandle = GetHandle()) != INVALID_HANDLE_VALUE) { ZeroMemory(&File_CreationTime, sizeof(FILETIME)); ZeroMemory(&File_LastAccessTime, sizeof(FILETIME)); ZeroMemory(&File_LastWriteTime, sizeof(FILETIME)); ZeroMemory(&Local_CreationTime, sizeof(SYSTEMTIME)); ZeroMemory(&Local_LastAccessTime, sizeof(SYSTEMTIME)); ZeroMemory(&Local_LastWriteTime, sizeof(SYSTEMTIME)); ZeroMemory(&UTC_CreationTime, sizeof(SYSTEMTIME)); ZeroMemory(&UTC_LastAccessTime, sizeof(SYSTEMTIME)); ZeroMemory(&UTC_LastWriteTime, sizeof(SYSTEMTIME)); if (GetFileTime(_FileHandle, &File_CreationTime, &File_LastAccessTime, &File_LastWriteTime)) { if (FileTimeToSystemTime(&File_CreationTime, &Local_CreationTime) && FileTimeToSystemTime(&File_LastAccessTime, &Local_LastAccessTime) && FileTimeToSystemTime(&File_LastWriteTime, &Local_LastWriteTime)) { SystemTimeToTzSpecificLocalTime(NULL, &UTC_CreationTime, &Local_CreationTime); SystemTimeToTzSpecificLocalTime(NULL, &UTC_LastAccessTime, &Local_LastAccessTime); SystemTimeToTzSpecificLocalTime(NULL, &UTC_LastWriteTime, &Local_LastWriteTime); } } CloseHandle(_FileHandle); } } } SYSTEMTIME FileInfo::GetCreationTime() { Init(); return Local_CreationTime; } SYSTEMTIME FileInfo::GetCreationTimeUTC() { Init(); return UTC_CreationTime; } SYSTEMTIME FileInfo::GetLastAccessTime() { Init(); return Local_LastAccessTime; } SYSTEMTIME FileInfo::GetLastAccessTimeUTC() { Init(); return UTC_LastAccessTime; } SYSTEMTIME FileInfo::GetLastWriteTime() { Init(); return Local_LastWriteTime; } SYSTEMTIME FileInfo::GetLastWriteTimeUTC() { Init(); return UTC_LastWriteTime; }
어떠한 파일의 시간 정보를 가져오려고 하면 Init 함수 부분에서
파일의 핸들을 유효성 검사 -> 유효하지 않다면 파일의 핸들을 가져오고 -> 유효하다면 ZeroMemory를 통해 9개의 구조체를 초기화 시키고
->GetFileTime 함수를 통해 FILETIME 구조체 형식의 시간 정보를 받아온 뒤 LocalTime(Non-UTC)와 UTC의 값을 초기화 하는 형식입니다.
그 뒤 Return을 통해 시간값을 반환하는데요, 이러한 방식의 구조가 성능상에 영향을 끼치는건 아닌지 궁금합니다.
파일의 시간을 요청할 때마다 핸들을 열고 작업이 끝나면 닫고, ZeroMemory를 통해 구조체를 초기화시키고 전부다 받아오는데
사실 이렇게 설계한 이유가 이 클래스는 FileInfo("파일 경로") 이렇게 지정이 됩니다.
단순하게 클래스를 "생성한 시점"에서의 파일의 정보만 가져오려고 했는데 곰곰히 생각해보니 "생성한 시점"이 아닌 지속적으로 "파일의 정보 함수"를 실행할 때 마다 파일의 정보를 가져오기로 해서 저렇게 설계를 했는데 어쩔 수 없는 방법인가요?
*함수를 호출할때마다 파일 핸들을 열고 9개의 구조체를 초기화시키고 끝나면 핸들을 닫고... 성능상에 부담이 갈 수도 있겠고, 이렇게 만들어 놓고 봐도 더러운 코드인지 깨끗한 코드인지 구별이 안갑니다.
*정말 단순하게 클래스를 생성한 시점에서의 파일 정보만 보여줘야 하는것인지.
*GetFileInformationByHandleEx함수를 사용해서 정보를 가져오려고하니 GetLastError()를 통해 오류 코드만 내뿜고 어디에도 예제를 찾기가 힘드네요.
좋은 방법 소개 부탁드립니다.
1.설명하신 내용과 코드가 안 맞는데요. 설명에
1.설명하신 내용과 코드가 안 맞는데요.
설명에 따르면, Init 함수에서 핸들(_FileHandle)이 유효(!=INVALID_HANDLE_VALUE)하다면 핸들을 가져오지 않고 ZeroMemory->GetFileTime으로 계속 실행해야 하는 거 아닙니까?
지금 코드는 Init 함수 아래의 모든 statement가 if(_FileHandle == INVALID_HANDLE_VALUE)에 묶여 있어서, 핸들이 유효하면 아무것도 실행 안 되는데요.
무슨 말이냐면, 만약 Init의 첫 호출이 성공해서 _FileHandle에 유효한 핸들 값이 저장되었다면, 이 값이 INVALID_HANDLE_VALUE로 되돌아가지 않으므로 두 번째 Init 호출부터는 아무 것도 안 한단 얘깁니다.
혹시 CloseHandle를 오버로드해서 핸들을 닫을 때 _FileHandle에 INVALID_HANDLE_VALUE를 덮어쓰게 했나요? 그렇게 했다면 말이 될 수도 있겠습니다만.
2.정말로 하고 싶으신 게 뭔가요?
FileInfo 클래스가 생성된 시점의 CreationTime, LastAccessTime, LastWriteTime을 반환하게 만들고 싶으신 거라면, 제시하신 것과 같은 Init 코드는 납득할 만합니다.
대신 그 함수는 생성자에서 한 번만 부르고, GetCreationTime 등에서는 Init을 다시 부르면 안 되겠죠.
Get*Time 함수를 호출할 때마다 정보를 읽어오게 하고 싶으신 거라면 지금 Init과 같은 코드는 낭비입니다. 심각한 정도는 아니지만, 굳이 이렇게 할 필요는 없다는 점에서 의아스럽기는 하네요.
예컨대 GetCreationTime 함수는 뭐하러 LastAccessTime 및 LastWriteTime을 다 조사하고 변환까지 하는 거죠? 그것도 매번 모든 변수를 ZeroMemory로 초기화까지 해가면서 말이죠. 그냥 CreationTime만 구해서 반환하면 되는 거 아닌가요?
파일 핸들은 매번 열고 닫는 방식을 취하든, 객체 생성할 때 열고 소멸할 때 닫든 일장일단이 있는 것 같습니다. 메서드 호출 빈도에 따라 달라질 것 같은데, 예컨대 빠르게 자주 호출된다면 계속 열어두는 게 낫겠지요.
3.무슨 일을 하고 계시는지는 잘 모르겠지만, 혹시 FindFirstChangeNotification 계열 API들이 조금 도움이 될지도 모르겠네요.
https://msdn.microsoft.com/ko-kr/library/windows/desktop/aa364417(v=vs.85).aspx
참조해보세요. 문제는 1)이 API는 디렉터리 단위로 동작하고, 2)Access Time이 바뀌는 건 못 잡아내는 모양입니다. 3)Wait Functions을 써야 하는데, 싱글 스레드 프로그램에 끼워넣기가 간단하지 않을 겁니다. 이미 멀티스레드 프로그램이라면 상관없겠지만요.
음?
그러고보니 코드가 좀 이상하네요.
새벽 4시에 짠 코드라 정상적이지 않나봅니다.
파일 핸들이 열려있다면 그냥 진행하고 열려있지 않다면 핸들을 열고 진행하고 해야하는데 코드가 좀 꼬여버렸네요.
질문의 요지를 잘 파악하신것 같아서 다행입니다. 코드낭비, 리소스 낭비를 묻는 질문인데
자기전에 문득 생각나는게 차라리 함수 하나하나에 대해 Init를 하는 것보다
파일의 정보가 있는 구조체를 생성한 후, 하나의 함수를 통해 모든 정보를 파싱하는게 더 효율적으로 보입니다.
좀더 편리한 함수가 있으면 좋을건데 신형 API들은 아무리 검색해봐도 예제가 잘 나오지 않으니 직접 해보는수밖에 없네요.
감사합니다.
참고해보세요.
GetFileTime function
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724320%28v=vs.85%29.aspx
FILETIME structure
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284%28v=vs.85%29.aspx
Retrieving the Last-Write Time
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724926%28v=vs.85%29.aspx
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
댓글 달기