C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 FAQ
C++Builder Programming FAQ
[39] 디스크 드라이브에 대한 모든! 정보를 구하기
박지훈.임프 [cbuilder] 23772 읽음    2001-11-12 07:35
최장민 님이 쓰신 글:
: 안녕하세요?
:
: 하드 디스크 C-Z 까지의 하드디스크 가 있다면 그각 드라이브마다의
: 전체 용량을 구하고 남은 용량도 구하는 프로그램을 만들고 싶은데
:
: 어떻게 하면 될까요?
:
: 전체 디스크 용량 구하기 / 시스템의 드라이브 수 구하기 / 남은 용량 구하기
:
: 이함수만 알면 될꺼 같은데..이 함수가 있는지 궁금합니다.
:   
:
: 그럼 모두 수고하세요



임펠리테리입니다.

먼저, 특정 드라이브의 남은 용량과 전체 용량 구하는 방법.
API 수준에서 드라이브의 남은 용량을 구하는 함수는 GetDiskFreeSpace()와 GetDiskFreeSpaceEx()
가 있는데, 앞의 GetDiskFreeSpace() 함수는 95 이상에서 사용가능하지만, 2기가바이트가 넘는
드라이브에 대해서는 엉터리값을 리턴합니다. 한편, NT와 윈95 OSR2 버전 이상에서는 이 함수 외에
GetDiskFreeSpaceEx()가 사용가능한데, 이 함수는 대용량 드라이브에 대해서도 정확한 값을 리턴
하는 반면, 윈95에서는 없는 함수이죠.

하지만 VCL에서는 이러한 문제를 다 해결한 시원~한 함수를 하나 제공하고 있습니다. DiskFree()
인데, 이 함수는 2기가바이트가 넘는 디스크에 대해서도 정확한 용량을 알려줍니다.
이 함수의 인자는 byte 숫자인데, 0 이면 현재 드라이브, 1 이면 A 드라이브, 2 면 B 드라이브...
이런 식입니다.

그런데.. 빌더에서 이 함수의 헬프를 찾아보면 나오는 예제 두개중 하나가 엉터리라서 이 함수
자체가 잘못된 것이 아닌가 하고 갸우뚱하게 만들죠. 빌더의 헬프에서는,

int AmtFree = DiskFree(0);
int Total = DiskSize(0);
S = IntToStr(AmtFree/Total) + " percent of the space on drive 0 is free: " (AmtFree/1024) + " Kbytes free. ";
Label1->Text = S;

이렇게 하면 된다고 되어 있지만, 사실 2기가바이트가 넘으면 int 값의 한계를 넘어버리므로
이 코드에서처럼 원래 __int64형인 DiskFree() 함수의 리턴값을 int 형으로 변환하게 되면
상위 4바이트의 값이 잘려버리므로 엉뚱한 값이 나옵니다.

두번째 예제에서는 비교적 정확한 예제를 보여줍니다.
Label1->Caption = IntToStr(DiskFree(0) / 1024) + " kilobytes.";
"비교적"이라고 말했지요? 여기서도 int형으로 다루기는 했습니다만, 그전에 1024로 나누어줬기
때문에, 2의 10승, 10비트 만큼은 정확해집니다. 다시 말하면, 2048 기가바이트까지는 정확한
값이 나옵니다. 물론 이 코드도 이 용량 이상의 드라이브가 출시된다면 엉터리 코드가 되겠지만,
__int64형은 계산하기가 까다롭다는 것을 생각하면 쓸만한 코드입니다.
하지만, "정확하지는 않다"는 것을 기억해두셔야 합니다.

디스크의 총 용량을 구하는 함수도 비슷한 이름입니다. DiskSize()이구요. 인자는 위 함수와
동일합니다. 사용법도 똑같습니다.

그다음으로.. 시스템의 드라이브들의 리스트 구하기.
이 기능에 대해서는 VCL버전의 함수가 없습니다. API 함수를 써야 하는데, API에는 이런 용도로
두가지의 함수가 준비되어 있습니다. GetLogicalDrives() 와 GetLogicalDriveStrings() 입니다.
GetLogicalDrives()는 인자는 없고 DWORD형을 리턴하는데, 이 리턴받은 값은 각 비트마다
각 알파벳 문자에 해당하는 드라이브가 존재하는지의 여부가 비트로 세팅되어 있습니다.
그러니 0번 비트가 세팅되어 있으면 A 드라이브가 존재하고, 1번 비트가 세팅되어 있지 않으면
B 드라이브는 존재하지 않는 것입니다. 그러니, 물론 비트연산을 해야 합니다.
다른 하나의 함수는 사용법이 조금더 까다롭습니다. GetLogicalDriveStrings() 함수는 각 드라이브
의 루트이름들을 NULL 문자로 나누어 버퍼에 넣어주는데, 예를 들어,
c:\<null>d:\<null><null>
이런 식입니다. 이렇게 널문자로 나누어진 스트링 리스트를 분석하는 것은 코드가 더 길어지므로,
차라리 앞의 함수를 써서 비트연산을 하는 편이 더 쉽습니다.

그외에, 드라이브에 대한 정보에 관련된 함수중 중요한 것들로는 GetDriveType() 함수와
GetVolumeInformation() 함수가 있습니다. GetDriveType() 함수는 지정한 드라이브의 타입
(하드디스크/시디롬/네트웍드라이브/리무버블/램드라이브)을 알아내는 함수로서 인자는 드라이브
루트패스를 받으며, 리턴값으로 종류를 판별합니다.
GetVolumeInformation()은 그외의 드라이브 관련 정보들, 즉 볼륨이름, 볼륨 시리얼넘버,
파일시스템 이름 등등을 알려줍니다.

이런 모든 정보를 다 알려주는 간단한 예제를 작성해봤습니다. 위에서 이해가 잘 안되시는 부분은
이 예제를 참고하시기 바랍니다.

먼저 새 프로젝트를 열고, 폼에 리스트박스 하나와 메모 하나를 배치합니다. 그리고 폼의
OnShow 핸들러를 만들고 내용을 다음과 같이 코딩합니다.

void __fastcall TForm1::FormShow(TObject *Sender)
{
     DWORD Drives = GetLogicalDrives();
     for(int Drv=0; Drv<26; Drv++)
           if((Drives >> Drv) & 0x00000001)
                 ListBox1->Items->Add((char)(Drv + 'A'));
}

이 코드는 리스트박스에 현재 컴퓨터에서 사용가능한 모든 드라이브들의 리스트를 보여줍니다.
예를 들어, 제 컴퓨터에서는 A C D G H I Z 이렇게 나옵니다.

그리고.. 리스트박스를 더블클릭해서 리스트박스의 OnClick 이벤트에 핸들러를 작성합니다.

void __fastcall TForm1::ListBox1Click(TObject *Sender)
{
     int DrvNo = ListBox1->Items->Strings[ListBox1->ItemIndex][1] - 'A';
     int FreeSpace = DiskFree(DrvNo+1) >> 10;
     int TotalSpace = DiskSize(DrvNo+1) >> 10;
     char DrvRoot[4] = "A:\\";
     DrvRoot[0] += DrvNo;
     char VolName[MAX_PATH], FileSysName[10];
     DWORD VolSerial;
     GetVolumeInformation(DrvRoot, VolName, sizeof(VolName), &VolSerial, NULL, NULL,
           FileSysName, sizeof(FileSysName));
     AnsiString DrvTypeString;
     switch(GetDriveType(DrvRoot))
     {
           case 0:                         DrvTypeString = "Unknown";               break;
           case 1:                         DrvTypeString = "(Not Available)";   break;
           case DRIVE_REMOVABLE: DrvTypeString = "Removable Drive";   break;
           case DRIVE_FIXED:       DrvTypeString = "Hard Drive";          break;
           case DRIVE_REMOTE:       DrvTypeString = "Network Drive";      break;
           case DRIVE_CDROM:       DrvTypeString = "CD-ROM Drive";       break;
           case DRIVE_RAMDISK:       DrvTypeString = "RAM Drive";         break;
     }
     Memo1->Lines->Clear();
     Memo1->Lines->Add(AnsiString("Volum Name : ") + VolName);
     Memo1->Lines->Add(AnsiString("Volum Serial : ") + IntToHex((int)VolSerial, 8));
     Memo1->Lines->Add(AnsiString("File System : ") + FileSysName);
     Memo1->Lines->Add(AnsiString("Drive Type : ") + DrvTypeString);
     Memo1->Lines->Add(AnsiString("Free Space : ") + FreeSpace + " KB");
     Memo1->Lines->Add(AnsiString("Total Space : ") + TotalSpace + " KB");
}

컴파일한 후 실행하면, 리스트박스에는 드라이브명들이 리스트되고, 각 드라이브를 선택할 때마다
그 드라이브에 대한 모든 정보가 메모에 리스트됩니다.

그럼 참고하시길...



+ -

관련 글 리스트
39 디스크 드라이브에 대한 모든! 정보를 구하기 박지훈.임프 23772 2001/11/12
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.