저번글에 이어서 이번 글에서는 로컬 디스크의 용량을 얻어오는 작업을 해보겠습니다.
디스크에는 전체 용량, 현재 용량, 사용 용량 등의 정보가 있습니다. 이러한 정보들은 GetDiskFreeSpace 함수를 써서 확인을 할 수 있습니다.
GetDiskFreeSpaceEx 함수 사용을 위해 필요한 요구사항은 아래와 같습니다.
지원되는 최소 클라이언트 | Windows XP |
지원되는 최소 서버 | Windows Server 2003 |
헤더 | fileapi.h (Windows.h) |
라이브러리 | Kernel32.lib |
DLL | Kernel32.dll |
GetDiskFreeSpaceEx 함수 원형은 아래와 같습니다.
BOOL GetDiskFreeSpaceExA(
LPCSTR lpDirectoryName, // 디스크의 디렉터리, NULL이면 현재 디렉터리
PULARGE_INTEGER lpFreeBytesAvailableToCaller, // 호출 스레드와 연결된 사용자가 사용 가능한 공간
PULARGE_INTEGER lpTotalNumberOfBytes, // 전체 공간
PULARGE_INTEGER lpTotalNumberOfFreeBytes // 사용 가능한 총 바이트 수
);
함수가 실패하면 0, 성공하면 0이 아닙니다. 실패 시 GetLastError를 통해 확인 할 수 있습니다.
예제 코드는 아래와 같습니다.
DWORD dwError = 0;
TCHAR tzDriveString[MAX_PATH] = { 0, };
// 반환 예 : "C:\\\0D:\\\0E:\\\0\0"
// 구분 : "\0", 끝 : "\0\0"
DWORD dwStringsLen = ::GetLogicalDriveStrings( MAX_PATH, tzDriveString ); // 로컬 디스크 목록 얻기
if ( dwStringsLen != 0 && dwStringsLen <= MAX_PATH )
{
CString strTrace;
strTrace.Format( _T( "Length : %lu" ), dwStringsLen );
TRACE( _T( "%s\n" ), strTrace );
DWORD dwIndex = 0;
while ( 0 < _tcslen( &tzDriveString[dwIndex] ) )
{
strTrace.Format( _T( "Drive : %s" ), &tzDriveString[dwIndex] );
TRACE( _T( "%s\n" ), strTrace );
ULARGE_INTEGER uliAvailable;
ULARGE_INTEGER uliTotal;
ULARGE_INTEGER uliFree;
CString strDrive;
strDrive.Format( _T( "%s" ), &tzDriveString[dwIndex] );
GetDiskFreeSpaceEx( strDrive, &uliAvailable, &uliTotal, &uliFree );
int iAvailable = (int)(uliAvailable.QuadPart >> 30);
int iTotal = (int)(uliTotal.QuadPart >> 30);
int iFree = (int)(uliFree.QuadPart >> 30);
TRACE( _T( "Disk(%s), 사용 중(%d), 전체(%d), 사용 가능(%d)\n" ), strDrive, iTotal - iFree, iTotal, iFree );
dwIndex += _tcslen( &tzDriveString[dwIndex] ) + 1;
}
}
else
dwError = ::GetLastError();
if ( dwError != 0 )
{
// 에러 처리
}
return;
추가적으로 설명을 드리자면, GetDiskFreeSpaceEx 함수의 2, 3, 4번째 인자는 ULARGE_INTEGER를 사용합니다. 여기에 입력된 변수에 디스크의 용량이 반환이 됩니다.
하지만 요새 디스크는 기가 혹은 테라로 지원하는데, 그렇게 되면 반환 되는 변수에는 엄청 큰 수가 들어있습니다.
그래서 단위를 변수에 입력된 값을 변환 해줘야하는데 이럴 경우 비트쉬프트를 사용하면 계산이 편합니다.
int iAvailable = (int)(uliAvailable.QuadPart >> 30);
int iTotal = (int)(uliTotal.QuadPart >> 30);
int iFree = (int)(uliFree.QuadPart >> 30);
오른쪽 쉬프트 30은 기가 단위로 표시하겠다는 겁니다. 30인 이유는 대략적으로 1기가는 2의 30승이기 때문이구요.
비슷하게 1메가 바이트는 약 2의 20승, 1키로 바이트는 약 2의 10승입니다.
저의 PC의 C:\의 용량을 출력해봤는데 동일하게 출력되었습니다.