1. 程式人生 > >windows磁碟相關API實踐說明

windows磁碟相關API實踐說明

API的列表如下,網上找的,我覺得還是蠻詳細的:

磁碟和驅動器管理API
GetLogicalDrivers      獲取主機中所有的邏輯驅動器,以BitMap的形式返回.
GetLogicalDriverString   獲取主機中所有的邏輯驅動器,以驅動器根路徑字串返回.
FindFirstVolume    查詢主機中的第一個驅動器,返回查詢控制代碼.
FindNextVolume     根據FindFirstVolume返回控制代碼,查詢主機中後繼的邏輯驅動器
FindVolumeClose    關閉驅動器查詢控制代碼
GetDriveType      獲取驅動器型別
GetVolumeInformation    獲取邏輯驅動器資訊
FindFirstVolumeMountPoint查詢指定卷的第一個掛載點,返回查詢控制代碼
FindNextVolumeMountPoint根據FindFirstVolumeMountPoint返回的控制代碼,查詢卷的後繼掛載點.
FindVolumeMountPointClose關閉掛載點查詢控制代碼
GetVolumeNameForVolumeMountPoint根據指定掛載點獲取相應的卷裝置名
SetVolumeMountPoint        將指定卷掛載到指定掛載點處
GetDiskFreeSpace           獲取磁碟空間資訊,包括每簇的扇區數,每扇區的位元組數,簇數量,空閒的簇數量
GetDiskFreeSpaceEx         獲取使用者可用的空閒空間的位元組數,磁碟總容量的位元組數

檔案和目錄管理API
DeleteFile                 刪除引數所指定檔案
CopyFile                   複製指定檔案為一個新檔案
MoveFile                   將指定檔案或目錄移動到指定位置
CreateFile                 新建或開啟一個檔案,獲取檔案控制代碼
ReadFile                   讀取由檔案控制代碼指定檔案的內容
WriteFile                  向由檔案控制代碼指定的檔案中寫入內容
GetFileSize                獲取檔案大小,返回DWORD中;大小超出DWORD最大值時可指定高32位的DWORD聯合儲存
GetFileSizeEx              獲取檔案大小,儲存到一個64位的大整數聯合體中.
CreateDirectory            建立一個目錄
GetCurrentDirectory        獲取當前程式所在目錄
SetCurrentDirectory        設定當前程式所在目錄
GetModuleFileName          獲取當前模組全路徑
FindFirstFile              查詢指定目錄下第一個檔案控制代碼或目錄,獲得查詢控制代碼
FindNextFile               根據FindFirstFile獲得的控制代碼,迴圈查詢檔案或目錄
GetFileAttributes          獲取指定檔案目錄屬性,返回一個DWORD值
GetFileAttributesEx        獲取檔案或目錄屬性,儲存在WIN32_FILE_ATTRIBUTE_DATA結構體中
SetFileAttributes          將檔案屬性設定為指定值
FileTimeToLocalFileTime    將檔案時間轉換為本地時間
FileTimeToSystemTime       將檔案轉換為系統時間,SYSTEMTIME格式便於顯示

高階檔案操作
CreateFileMapping          建立檔案的對映物件
MapViewOfFile              建立檢視,將建立的檔案對映物件對映到當前程序的地址空間中
FlushViewOfFile            將檢視中的資料都寫入磁碟,對檢視的操作都會反映到磁碟上的檔案中
OpenFileMapping            開啟已經存在的命名的檔案對映物件
UnmapViewOfFile            取消檔案對映
GetMappedFileName          從對映物件獲取被對映檔案的檔案裝置名
QueryDosDevice             獲取MS-DOS裝置名

GetLocalDrivers

       最近真的是發現做文件也是一種習慣啊。慢慢來吧。

       第一個函式GetLocalDrivers這個函式的返回值是一個DWORD,也就是以Bitmap形式返回相關的資訊,從0位開始為A盤,從以往後遞迴就是BCD……

       這個函式無引數,函式原型如下:

DWORDGetLogicalDrives(VOID);

程式碼執行結果:

 

可以對應一下,確實是正確的。不過H位為0應該是因為這光碟機中無光碟。/*此處錯誤,0對應的是I盤,時間久遠,估計是因為但是U盤被拔掉了。H盤位置對應的確實是1*/

GetLogicalDriveStrings

       這個函式還挺有意思的,可以用於獲取目前系統上所有的碟符,有趣就在於其字串的排列方式。函式原型如下:

DWORD GetLogicalDriveStrings(  DWORD nBufferLength,  // size of buffer

                                                      LPTSTRlpBuffer       // drive strings buffer);

       然後看下函式呼叫後其在緩衝區引數的結果:

 

       很有趣吧,哈哈,反正我是第一次見到。

       然後下面展示下這個字串是如何結束的:

 

       最後面連續的兩個0值表明字串都已結束。好玩的很。

FindFirstVolume

       這個函式能獲取計算機上的第一個卷,並且返回一個控制代碼,用於FindNextVolume函式的使用。函式原型如下:

HANDLE FindFirstVolume(  LPTSTR lpszVolumeName,   // output buffer

DWORD cchBufferLength    // size of output buffer);

演示結果:

      

這個函式我在使用的時候還遇到了一點小小的麻煩,就是最初我設定緩衝區大小為32,結果,返回了一個無效控制代碼……後來改的256,才正常工作了。

FindNextVolume

       這個函式時要配合著上面函式返回的控制代碼使用的函式,函式原型如下:

       BOOLFindNextVolume(  HANDLE hFindVolume,      // volume search handle

            LPTSTR lpszVolumeName,   // output buffer

            DWORD cchBufferLength    // size of output buffer);

貼下執行截圖:

 

在這裡你可能要問,上面這一串資料都是什麼,我的回答:我也不知道。

FindVolumeClose

這個函式的作用就是單純的關閉上面那個查詢控制代碼的。不多說了。

GetDriveType

這個函式的作用是根據碟符來確定驅動器的型別。且看函式原型如下:

UINTGetDriveType(  LPCTSTRlpRootPathName   // root directory);

       這裡引數是就是路徑名,當然了,只有一個碟符,如CDEF,這個引數可以通過上面的一個函式GetLogicalDriveString的結果來使用。返回值就是驅動器型別了。型別表如下:

 

我寫了個專用函式,如下:

複製程式碼
 1 //僅?限T單Ì£¤線?程¨¬使º1用®?
 2 
 3 LPCTSTR GetTypeString(LPCTSTR lpDriverRoot)
 4 
 5 {
 6 
 7      static LPCTSTR Buf[7] = \
 8 
 9      {
10 
11          _T("UNKNOWN"),
12 
13          _T("NO_ROOT_DIR"),
14 
15          _T("REMOVABLE"),
16 
17          _T("FIXED"),
18 
19          _T("REMOTE"),
20 
21          _T("CDROM"),
22 
23          _T("RAMDISK"),
24 
25      };
26 
27      int nAddr = -1;
28 
29      switch(GetDriveType(lpDriverRoot))
30 
31      {
32 
33      case DRIVE_UNKNOWN:
34 
35          nAddr = 0;
36 
37          break;
38 
39      case DRIVE_NO_ROOT_DIR:
40 
41          nAddr = 1;
42 
43          break;
44 
45      case DRIVE_REMOVABLE:
46 
47          nAddr = 2;
48 
49          break;
50 
51      case DRIVE_FIXED:
52 
53          nAddr = 3;
54 
55          break;
56 
57      case DRIVE_REMOTE:
58 
59          nAddr = 4;
60 
61          break;
62 
63      case DRIVE_CDROM:
64 
65          nAddr = 5;
66 
67          break;
68 
69      case DRIVE_RAMDISK:
70 
71          nAddr = 6;
72 
73          break;
74 
75      default:
76 
77          return NULL;
78 
79      }
80 
81      return Buf[nAddr];
82 
83 }
複製程式碼

執行結果:

 

這裡截圖只有一部分,顯示了磁碟和光碟的區別。

GetVolumeInformation

       這個函式還是比較複雜的,無他,引數太多了,且看函式原型:

BOOL GetVolumeInformation(  LPCTSTR lpRootPathName,           // root directory

  LPTSTR lpVolumeNameBuffer,        // volume name buffer

  DWORD nVolumeNameSize,            // length of name buffer

  LPDWORD lpVolumeSerialNumber,     // volume serial number

  LPDWORD lpMaximumComponentLength, // maximum file name length

  LPDWORD lpFileSystemFlags,        // file system options

  LPTSTR lpFileSystemNameBuffer,    // file system name buffer

  DWORD nFileSystemNameSize         // length of file system name buffer);

一共8個引數,真要命。

這個函式的作用是用來獲取指定路徑的檔案系統以及卷資訊q其中有五個引數都是輸出型引數。下面看下兩個NameBuffer都返回的是什麼。

 

  這裡看到lpVolumeNameBuffer引數返回的是驅動器的名字,這裡系統盤是win7,而其他盤因為未命名所以什麼也沒有。

       lpFileSystemNameBuffer引數則是用於返回檔案系統型別。這裡能看到,硬碟的檔案系統是NTFS。後面因為我的筆記本中插著U盤,所以其 顯示結果是FAT32.

       而lpVolumeSerialNumber引數返回的是序列號,這個引數具體的用處我也不是很清楚。

       lpMaximumComponentLength引數返回的是檔案系統支援的檔名最大長度。255還是很大的。

       lpFileSystemFlags檔案系統選項的標誌位,還是所謂的文圖返回吧。這個引數有個專門的列表:

這種表就屬於那種一看就頭大的表,還是寫個函式看一下比較靠譜。

 

函式實現:

複製程式碼
 1 void CheckFileSystemFlag(DWORD FSF)
 2 {
 3     //我是不是應該用個結構體做?
 4     static LPCTSTR lpList[12] = 
 5     {
 6         _T("The file system preserves the case of file names when it places a name on disk."),
 7         _T("The file system supports case-sensitive file names."),
 8         _T("The file system supports Unicode in file names as they appear on disk."),
 9         _T("The file system preserves and enforces ACLs. For example, NTFS preserves and enforces ACLs, and FAT does not."),
10         _T("The file system supports file-based compression."),
11         _T("The specified volume is a compressed volume; for example, a DoubleSpace volume."),
12         _T("The file system supports named streams."),
13         _T("The file system supports the Encrypted File System (EFS)."),
14         _T("The file system supports object identifiers."),
15         _T("The file system supports reparse points."),
16         _T("The file system supports sparse files."),
17         _T("The file system supports disk quotas.")
18     };
19     static const DWORD FlagList[12] = 
20     {
21         FS_CASE_IS_PRESERVED,
22         FS_CASE_SENSITIVE,
23         FS_UNICODE_STORED_ON_DISK,
24         FS_PERSISTENT_ACLS,
25         FS_FILE_COMPRESSION,
26         FS_VOL_IS_COMPRESSED,
27         FILE_NAMED_STREAMS,
28         FILE_SUPPORTS_ENCRYPTION,
29         FILE_SUPPORTS_OBJECT_IDS,
30         FILE_SUPPORTS_REPARSE_POINTS,
31         FILE_SUPPORTS_SPARSE_FILES,
32         FILE_VOLUME_QUOTAS
33     };
34     for(int i = 0;i < 12;++ i)
35     {
36         if(FSF & FlagList[i])
37             wcout << lpList[i] << endl;
38     }
39 }
複製程式碼

可以對照一下結果,能發現,NTFS僅僅沒有壓縮卷這一項。而FAT32則只有兩個結果。檔案系統的差別還是挺大的。

FindFirstVolumeMountPoint

       這個函式的原型如下:

HANDLE FindFirstVolumeMountPoint(  LPTSTR lpszRootPathName,     // volume name

  LPTSTR lpszVolumeMountPoint, // output buffer

  DWORD cchBufferLength        // size of output buffer);

這裡第一個引數是使用FindFirstVolume的的volume字串,也就是很長的那一串。但是在我的計算機上,這個函式的返回值始終都是失敗,而且現在也沒理解所謂的掛載是什麼意思。這幾個函式暫且擱置。

GetDiskFreeSpace

這個函式是用來獲取磁碟資訊的。函式原型如下:

BOOL GetDiskFreeSpace(  LPCTSTR lpRootPathName,          // root path

  LPDWORD lpSectorsPerCluster,     // sectors per cluster

  LPDWORD lpBytesPerSector,        // bytes per sector

  LPDWORD lpNumberOfFreeClusters,  // free clusters

  LPDWORD lpTotalNumberOfClusters  // total clusters);

       第一個引數就是路徑名,比如C:\。演示下執行結果:

 

這個函式沒大多好說的,看了就會用。