[提出問題]
最近我正在開發一個程序,任務是從CD-ROM上讀取文件,如視頻和音頻文件。因為每一台機器上的情況都不一樣。如何知道CD-ROM驅動器呢?
[解答]
首先,一台機器可能有不止一個CD-ROM驅動器。現在CD-ROM已經是PC機的標准配置,此外再裝個可擦寫的光盤驅動,甚至是DVD都是很常見的事情。不管一台機器上裝多少個不同的驅動器,如何找到它們呢?
有關驅動器的函數有GetLogicalDrives,GetLogicalDriveStrings和GetDriveType。前兩個用來獲取邏輯驅動器盤符,GetLogicalDriveStrings返回路徑名字符串,如:
"A:\<null>C:\<null>F:\<null><null>"
這裡每一個路徑名都由NULL(空或者零)字符分隔,最後結尾是兩個空字符--這是標准的C風格處理方法。對於喜歡操作位和字節的匯編語言使用者來說,GetLogicalDrives是個很好用的API函數。它以位掩碼的形式返回邏輯驅動器。即在一個DWORD類型的返回值中,位0(最小的一位)表示驅動器A,位1表示驅動器B,以此類推。每一個位的狀態如果是on,則表示對應的邏輯驅動器存在;否則狀態為off,表示對應的邏輯驅動器不存在。大家知道DWORD是一個32位的值,足以包括所有的英文字母,也就是說最多可有26個盤符。
為了確定某個邏輯驅動器的類型,必須調用GetDriveType函數。它以路徑名作為參數(如C:\),返回DRIVE_FIXED,DRIVE_REMOVABLE,或DRIVE_UNKNOWN。下面列出了所有可能返回的值:這些值在winbase.h定義
#define DRIVE_UNKNOWN 0 // 無效路徑名
#define DRIVE_NO_ROOT_DIR 1 // 無效路經,如無法找到的卷標
#define DRIVE_REMOVABLE 2 // 可移動驅動器(如磁盤驅動器,光驅等)
#define DRIVE_FIXED 3 // 固定的驅動器 (如 通常的硬盤)
#define DRIVE_REMOTE 4 // 網絡驅動器
#define DRIVE_CDROM 5 // CD-ROM
#define DRIVE_RAMDISK 6 // 隨機存取(RAM) 磁盤
為了更容易說明問題,我寫了一個小程序--ListDrives,它可以列出某台機器上所有的邏輯驅動器。其實現代碼如下:ListDrives.cpp
#include "stdafx.h"
#include "resource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
using namespace std; // for string class
// 下面是一個GetDriveType返回碼與人可讀字符串的迷你對照表
//
struct {
UINT type; // GetDriveType返回碼類型
LPCSTR name; // ascii 名稱
} DriveTypeFlags [] = {
{ DRIVE_UNKNOWN, "未知" },
{ DRIVE_NO_ROOT_DIR, "無效路經" },
{ DRIVE_REMOVABLE, "可移動" },
{ DRIVE_FIXED, "固定" },
{ DRIVE_REMOTE, "網絡驅動器" },
{ DRIVE_CDROM, "CD-ROM" },
{ DRIVE_RAMDISK, "隨機存取磁盤" },
{ 0, NULL},
};
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) {
cerr << _T("Fatal Error: MFC initialization failed") << endl;
return -1;
}
// 獲取邏輯驅動器字符串- a:\b:\c:\... 等.
// 還可以用GetLogicalDrives 以位圖形式代替字符串形式獲取信息
TCHAR buf[100];
DWORD len = GetLogicalDriveStrings(sizeof(buf)/sizeof(TCHAR),buf);
// 顯示每個驅動器的信息
//
string msg = "Logical Drives:\n"; // STL string
for (TCHAR* s=buf; *s; s+=_tcslen(s)+1) {
LPCTSTR sDrivePath = s;
msg += sDrivePath;
msg += " ";
// GetDriveType 獲取枚舉值,如DRIVE_UNKNOWN等.
//
UINT uDriveType = GetDriveType(sDrivePath);
// 查找驅動器類型。在此我用了表(結構數組)來進行查找處理,過於繁瑣了一些,
// 但既然uDriveType 的值是連續的。
// 我可以用DriveTypeFlags[uDriveType]來代替線性查找。在實際的編程中通常可以這麼做:
// if (uDriveType & DEVICE_CDROM) {
……
// }
//
for (int i=0; DriveTypeFlags[i].name; i++) {
if (uDriveType == DriveTypeFlags[i].type) {
msg += DriveTypeFlags[i].name;
break;
}
}
msg += ''''''''''''''''\n '''''''''''''''';
}
cout << msg.c_str();
return 0;
}
程序代碼很簡單,它是一個MFC程序。用GetLogicalDriveStrings獲取所有邏輯驅動器的根路徑名,然後調用GetDriveType來確定每個驅動器的類型。如果你要找CD-ROM,則檢查uDriveType = DRIVE_CDROM就可以了。
本文配套源碼