1. windows 下磁盤文件讀寫windows
下面是讀取D:\磁盤上的第0扇區 512 Bytes數組
CreateFile()打開磁盤,獲取文件句柄;緩存
SetFilePointer()設置讀寫的位置;安全
ReadFile()讀取磁盤扇區數據。服務器
HANDLE hFile;
char drive[] = "\\\\.\\D:"; //------- \\.\D: ----- //------- 建立文件句柄 ------ hFile = CreateFile(drive, // 還能夠爲硬盤"\\\\.\\physicalDrive0"絕對讀寫, 或相似"D:\\abc\\fileName.txt"文件形式, GENERIC_READ, // 打開方式 FILE_SHARE_WRITE|FILE_SHARE_READ, // 前者表示以後打開該文件的程序 only write, 後者爲only read NULL, // 安全屬性 LPSECURITY_ATTRIBUTES OPEN_EXISTING, // how to Create 0, NULL); // if(hFile == INVALID_HANDLE_VALUE) return;
// 中間兩個參數分別是偏移字節數的低32Bit數值,和高32Bit的地址, 高32Bit不用則爲零; 此處表示D:\從首扇區起,偏移字節數爲0
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
DWORD lenRead;
ReadFile(hFile, buf, 512, &lenRead, NULL); // 在設定的位置起,讀取512Byte到緩存buf; 這裏讀取的是分區引導扇區
2. 獲取磁盤全部驅動器app
DWORD allDrive = GetLogicalDrive(). // 返回值共有 32 Bits,從低位到高位分別表示A,B,C,D,E,..... // 好比0x0000 007C, 即 01111100, 表示有C,D,E,F,G 共5個驅動器;
3. NTFS 文件系統ide
一個NTFS系統是由引導扇區,主文件表MFT,和數據區組成;另外MFT有一部分重要備份在數據區。函數
(1) 引導扇區編碼
若果D:\盤是NTFS文件系統,那麼上面獲得的第0個扇區數據 buf 偏移0x03開始的8個Bytes就是"NTFS ",表示這個扇區就是NTFS加密
的引導記錄。這第0個扇區也就是$Boot扇區,這個扇區包含了該卷的 BPB 和擴展BPB參數,能夠獲得該卷的卷大小,磁頭數,扇區大小,簇
大小等等參數;要解析一個NTFS卷的文件結構也是從這裏的BPB參數開始的。
解析時有用到的是這個扇區的前 88 (0x58) 個Bytes,剩餘的是引導代碼和結束標誌"55 AA",前88個字節具體結構以下:
1 typedef struct NTFS_BPB{ // 在cmd 輸入 fsutil fsinfo ntfsinfo d: 查詢 NTFS 信息 2 UCHAR jmpCmd[3]; 3 UCHAR s_ntfs[8]; // "NTFS " 標誌 4 // 0x0B 5 UCHAR bytesPerSec[2]; // 0x0200 扇區大小,512B 6 UCHAR SecsPerClu; // 0x08 每簇扇區數,4KB 7 UCHAR rsvSecs[2]; // 保留扇區 8 UCHAR noUse01[5]; //
9 // 0x15 10 UCHAR driveDscrp; // 0xF8 磁盤介質 -- 硬盤 11 UCHAR noUse02[2]; //
12 // 0x18 13 UCHAR SecsPerTrack[2]; // 0x003F 每道扇區數 63 14 UCHAR Headers[2]; // 0x00FF 磁頭數 15 UCHAR secsHide[4]; // 0x3F 隱藏扇區 16 UCHAR noUse03[8]; // 17 // 0x28 18 UCHAR allSecsNum[8]; // 卷總扇區數, 高位在前, 低位在後 19 // 0x30 20 UCHAR MFT_startClu[8]; // MFT 起始簇 21 UCHAR MFTMirr_startClu[8]; // MTF 備份 MFTMirr 位置 22 //0x40 23 UCHAR cluPerMFT[4]; // 每記錄簇數 0xF6 24 UCHAR cluPerIdx[4]; // 每索引簇數 25 //0x48 26 UCHAR SerialNum[8]; // 卷序列號
27 UCHAR checkSum[8]; // 校驗和 28 }Ntfs_Bpb,*pNtfs_Bpb;
(2) 關於簇
在一個分區中引導記錄扇區所在的簇編號爲0,日後的簇編號1,2,3等等一直到卷尾,這就是一個分區的邏輯簇號(LCN);計算
邏輯扇區號:LCN * 簇大小,簇的大小在BPB參數中找到,通常爲8個扇區4KB;以此能夠由 MFT 起始簇 MFT_startClu 計算
出第一個 MFT 項(記錄)的位置。
VCN,虛擬簇號,給一個文件從它的首簇開始編號,爲0,依次遞增一直到文件的尾簇,在物理上不必定連續。
(3) 主文件表 (Master File Table, MFT)
MFT 是由一條條 MFT 項(記錄)所組成的,並且每項大小是固定的(通常爲1KB),MFT保留了前16項用於特殊文件記錄,稱爲元數據,
元數據在磁盤上是物理連續的,編號爲0~15;若是$MFT的偏移爲0x0C0000000, 那麼下一項的偏移就是0x0C0000400,在下一項就是
0x0C0000800等等;
MFT記錄了整個卷的全部文件 (包括MFT自己、數據文件、文件夾等等) 信息,包括空間佔用,文件基本屬性,文件位置索引,建立時
間用戶權限,加密信息等等,每個文件在 MFT 中都有一個或多個 MFT 項記錄文件屬性信息,這裏的屬性包括數據,若是這個文件很小
在 MFT 項中就能夠放下,那麼這條屬性就定義爲常駐屬性,常駐標誌位記爲1,若是是很是駐,則有一個索引指向另外一條記錄(稱爲一個運行)。
(3) 第一條 MFT 項: $MFT
MFT 的第一項記錄$MFT描述的是主分區表MFT自己,它的編號爲0,MFT項的頭部都是以下結構:
1 typedef struct MFT_HEADER{ 2 UCHAR mark[4]; // "FILE" 標誌 3 UCHAR UsnOffset[2]; // 更新序列號偏移 30 00 4 UCHAR usnSize[2]; // 更新序列數組大小+1 03 00 5 UCHAR LSN[8]; // 日誌文件序列號(每次記錄修改後改變) 58 8E 0F 34 00 00 00 00 6 // 0x10 7 UCHAR SN[2]; // 序列號 隨主文件表記錄重用次數而增長 8 UCHAR linkNum[2]; // 硬鏈接數 (多少目錄指向該文件) 01 00 9 UCHAR firstAttr[2]; // 第一個屬性的偏移 38 00 10 UCHAR flags[2]; // 0已刪除 1正常文件 2已刪除目錄 3目錄正使用 11 // 0x18 12 UCHAR MftUseLen[4]; // 記錄有效長度 A8 01 00 00 13 UCHAR maxLen[4]; // 記錄佔用長度 00 04 00 00 14 // 0x20 15 UCHAR baseRecordNum[8]; // 索引基本記錄, 若是是基本記錄則爲0 16 UCHAR nextAttrId[2]; // 下一屬性Id 07 00 17 UCHAR border[2]; // 18 UCHAR xpRecordNum[4]; // 用於xp, 記錄號 19 // 0x30 20 UCHAR USN[8]; // 更新序列號(2B) 和 更新序列數組 21 }Mft_Header, *pMft_Header;
上面的頭部結構體在扇區的數據偏移 0x00 ~0x38;
在0x38以後的4大塊顏色數據是4條屬性,描述名稱,時間,索引等等信息,最後以"FF FF FF FF"結束。它們分別以0x10,0x30,
0x80, 0xB0做爲標誌;這裏的四種屬性所描述的的信息類型能夠由下表查得,對照數據和結構體能夠把這4條屬性解析出來。
1 //------------------ 屬性頭通用結構 ---- 2 typedef struct NTFSAttribute //全部偏移量均爲相對於屬性類型 Type 的偏移量 3 { 4 UCHAR Type[4]; // 屬性類型 0x10, 0x20, 0x30, 0x40,...,0xF0,0x100 5 UCHAR Length[4]; // 屬性的長度 6 UCHAR NonResidentFiag; // 是不是很是駐屬性,l 爲很是駐屬性,0 爲常駐屬性 00 7 UCHAR NameLength; // 屬性名稱長度,若是無屬性名稱,該值爲 00 8 UCHAR ContentOffset[2]; // 屬性內容的偏移量 18 00 9 UCHAR CompressedFiag[2]; // 該文件記錄表示的文件數據是否被壓縮過 00 00 10 UCHAR Identify[2]; // 識別標誌 00 00 11 //--- 0ffset: 0x10 --- 12 //-------- 常駐屬性和很是駐屬性的公共部分 ---- 13 union CCommon 14 { 15 //---- 若是該屬性爲 常駐 屬性時使用該結構 ---- 16 struct CResident 17 { 18 UCHAR StreamLength[4]; // 屬性值的長度, 即屬性具體內容的長度。"48 00 00 00" 19 UCHAR StreamOffset[2]; // 屬性值起始偏移量 "18 00" 20 UCHAR IndexFiag[2]; // 屬性是否被索引項所索引,索引項是一個索引(如目錄)的基本組成 00 00 21 }; 22 //------- 若是該屬性爲 很是駐 屬性時使用該結構 ---- 23 struct CNonResident 24 { 25 UCHAR StartVCN[8]; // 起始的 VCN 值(虛擬簇號:在一個文件中的內部簇編號,0起) 26 UCHAR LastVCN[8]; // 最後的 VCN 值 27 UCHAR RunListOffset[2]; // 運行列表的偏移量 28 UCHAR CompressEngineIndex[2]; // 壓縮引擎的索引值,指壓縮時使用的具體引擎。 29 UCHAR Reserved[4]; 30 UCHAR StreamAiiocSize[8]; // 爲屬性值分配的空間 ,單位爲B,壓縮文件分配值小於實際值 31 UCHAR StreamRealSize[8]; // 屬性值實際使用的空間,單位爲B 32 UCHAR StreamCompressedSize[8]; // 屬性值通過壓縮後的大小, 如未壓縮, 其值爲實際值 33 }; 34 }; 35 };
由這個結構體能夠知道,屬性頭的長度取決因而否有屬性名,屬性名長度是多少;是否常駐,若是常駐,屬性內容長度是多少,若是很是駐,運行列表有多長。
(0x08)日誌文件序列號,它又叫文件參考號、文件引用號,一共 8Byte,前6個字節是文件稱爲文件號;後2個字節是文件順序號,文件順序號隨重用而增長。
10H 類型:10H屬性$STANDART_INFORMATION,描述的是文件的建立、訪問、修改時間,傳統屬性,以及版本信息等等。
1 struct Value0x10 2 { 3 UCHAR fileCreateTime[8]; // 文件建立時間 4 UCHAR fileChangeTime[8]; // 文件修改時間 5 UCHAR MFTChangeTime[8]; // MFT修改時間 6 UCHAR fileLatVisited[8]; // 文件最後訪問時間 7 UCHAR tranAtrribute[4]; // 文件傳統屬性 8 UCHAR otherInfo[28]; // 版本,全部者,配額,安全等等信息(詳細略) 9 UCHAR updataNum[8]; // 文件更新序列號 10 };
下面的偏移都是相對於屬性首字節,其值加上0x38 就是實際偏移(圖中的offset)。
0x00 4B: (0x10) 類型標誌
0x04 4B: (0x60) 整條10H屬性的長度
0x08 1B: (0x00) 很是駐
0x09 1B: (0x00) 無屬性名稱
0x0A 2B: (0x18) 屬性內容偏移位置
0x18 8B: (ED 46 39 6B 6B 93 CF 01) 8個字節是文件建立時間,緊隨其後的3x8個字節分別是文件最後修改時間,MFT修改
時間,文件最後訪問時間。64位數值是相對於1601-01-01零點整的千萬分之一秒數。能夠用FileTimeToSystemTime()轉換成
咱們一般見到的形式。
0x38 8B: (06 00 00 00 00 00 00 00)傳統屬性,這裏是系統隱含文件,位描述:
後面還有0x28個字節是版本和管理信息等等。
20H類型 $ATTRIBUTE_LIST
當一個文件須要多個MFT項來記錄,20H是用來描述屬性的屬性列表;當很是駐屬性依然不夠空間,則須要屬性列表。20H類屬性也有
可能爲常駐或很是駐,能夠應用上面的通用屬性頭。以此結構體獲得屬性值的偏移地址,進而獲得屬性內容。
//------- 這個結構只是數據內容部分,不包括屬性頭 NTFSAttribute ----
//------- 由屬性頭的屬性值偏移量肯定屬性值的起始位置 ---
1 struct Value0x20{ 2 UCHAR type[4]; // 類型 3 UCHAR recordType[2]; // 記錄類型 4 UCHAR nameLen[2]; // 屬性名長度 5 UCHAR nameOffset; // 屬性名偏移 6 UCHAR startVCN[8]; // 起始 VCN 7 UCHAR baseRecordNum[8]; // 基本文件記錄索引號 8 UCHAR attributeId[2]; // 屬性 id 9 //---- 屬性名(Unicode) 長度取決於 nameLen 的值 --- 10 };
30H 類型 $FILE_NAME
30H 類型屬性描述的是文件或文件夾的名字和建立基本信息,屬性頭不在贅述,屬性值的結構以下:
1 struct Value0x30 2 { 3 UCHAR parentFileNum[8]; // 父目錄的文件參考號,前6B 4 UCHAR createTime[8]; // 文件建立時間 5 UCHAR changeTime[8]; // 文件修改時間 6 UCHAR MFTchangeTime[8]; // MFT 修改時間 7 UCHAR lastVisitTime[8] // 最後一次訪問時間 8 UCHAR AllocSize[8]; // 文件分配大小 9 UCHAR realSize[8]; // 實際大小 10 UCHAR fileFlag[4]; // 文件標誌,系統 隱藏 壓縮等等 11 UCHAR EAflags[4] // EA擴展屬性和重解析點 12 UCHAR nameLength; // 文件名長 13 UCHAR nameSpace; // 文件命名空間 14 //----- Name (Unicode編碼) 長度爲 2 * nameLength ---- 15 }
NTFS經過爲一個文件建立多個30H屬性實現POSIX (Portable Operating System Interface, 可移植操做系統接口) 式硬鏈接,
每一個30H屬性都有本身的詳細資料和父目錄;一個硬鏈接刪除時,就從MFT中刪除這個文件名,最後一個硬鏈接被刪除時,這個文件就算是
真正被刪除了。
文件參考號:包括前 6B 的文件記錄號,後 2B 的文件引用計數;當文件記錄號爲0x05時,是根目錄。
命名空間:0 --- POSIX, 1 -- Win32, 2 --- DOS, 3 --- Win32 & DOS
40H 屬性 $OBJECT_ID
MTFS統一給全部 MFT 記錄分配的一個標識 --- 對象ID,即結構體第一個16B,可能只有一個全局對象ID,後面的3個ID可能沒有。
1 struct Value0x40 2 { 3 UCHAR GObjectId[16]; // 全局對象ID 給文件的惟一ID號 4 UCHAR GOriginalVolumeId[16]; // 全局原始卷ID 永不改變 5 UCHAR GOriginalObjectId[16]; // 全局原始對象ID 派給本MFT記錄的第一個對象ID 6 UCHAR GDomain[16]; // 全局域ID (未使用) 7 };
50H 屬性 $SECURITY_DESCRIPTOR ( 安全描述符) 略。
60H 屬性 $VOLUME_NAME 卷名屬性
1 struct Value0x60 2 { 3 //---- 通用屬性頭 -- 4 UCHAR VolumeName[N]; //(Unicode) N 最大爲 127 外加一個結束符'\0' 5 };
70H 屬性 $VOLUME_INFORMATION 卷版本、狀態
1 struct Value0x70 2 { //----- 通用屬性頭 --- 3 UCHAR noUsed1[8]; // 00 4 UCHAR mainVersion; // 主版本號 1--winNT, 3--Win2000/XP 5 UCHAR SecVersion; // 次版本號 當主爲3, 0--win2000, 1--WinXP/7 6 UCHAR flag[2]; // 標誌 7 UCHAR noUsed2[4]; // 00 8 }; 9 /* flag: 10 * 0x0001 壞區標誌 下次重啓時chkdsk/f進行修復 11 * 0x0002 調整日誌文件大小 12 * 0x0004 更新裝載 13 * 0x0008 裝載到 NT4 14 * 0x0010 刪除進行中的USN 15 * 0x0020 修復對象 Ids 16 * 0x8000 用 chkdsk 修正卷 17 */
80H 屬性 $DATA 容納文件數據(未命名數據流),文件的大小通常指是未命名數據流的大小,沒有長度限制,當它爲常駐時,數據
長度最小。它的結構爲屬性頭加上數據流,若是數據流太大,則標記爲很是駐,以運行的方式索引到外部。例如找一個MP3文件,從它的MFT
項中0x80屬性中能夠看到它必定是很是駐,它的運行所指向的一系列簇就是音樂文件數據流;
一個80H屬性實例:
0x00~0x37 是屬性頭;運行列表偏移是紫色和橙色區域,0x40開始,能夠獲得運行列表 32 40 34 00 00 0C 32 80 31 07 54 16 ;分析以下:
首先0x32,低4位是2,表示緊隨其後的2Byte 0x3440做爲運行簇大小,高4位是3,表示簇大小以後的3個Byte 0x0C0000 是起始簇,這
是一個運行結束;接下來的0x32同理得簇起始號0x165407,運行大小爲0x3180簇;一個運行的結束後跟0x00 爲列表結束,以後填充無效字符。
90H 屬性 $INDEX_ROOT 索引根。實現NTFS的B+樹索引的根節點,老是常駐。索引根屬性由屬性頭、索引根和索引項組成。屬性頭是通用
屬性頭的常駐部分。結構體以下(可能有些誤差):
1 struct indexHeader 2 { 3 UCHAR type[4]; // 屬性類型 4 UCHAR checkRule[4]; // 校對規則 5 UCHAR allocSize[4]; // 索引項分配大小 6 UCHAR CluPerIdx; // 每索引記錄的簇數 7 UCHAR noUse01[3]; // 填充 8 9 UCHAR firstIdxOffset[4]; // 第一個索引項偏移 10 UCHAR idxTotalSize[4]; // 索引項總大小 11 UCHAR indxAllocSize[4]; // 索引項分配大小 12 UCHAR flag; // 標誌 13 UCHAR noUse02[3]; 14 }; 15 // 通常小目錄在90屬性中有常駐目錄項,目錄項的結構與INDX緩存中的目錄項同樣 16 struct indexItem 17 { 18 UCHAR MFTnum[8] // 文件的 MFT 記錄號,前6B是MFT編號,用於定位此文件記錄 19 UCHAR ItemLen:[2]; // 索引項大小 20 UCHAR IndexIdentifier:[2]; // 索引標誌 R 21 UCHAR isNode[2]; // 1---此索引包含一個子節點,0---此爲最後一項 22 UCHAR noUse03[2]; // 填充 23 UCHAR FMFTnum[8]; // 父目錄 MFT文件參考號 0x05表示根目錄 24 UCHAR CreateTime[8]; //文件建立時間 25 UCHAR fileModifyTime[8]; //文件修改時間 26 UCHAR MFTModifyTime[8]; //文件記錄最後修改時間 27 UCHAR LastVisitTime[8]; //文件最後訪問時間 28 UCHAR FileAllocSize[8]; //文件分配大小 (B) 29 UCHAR FileRealSize[8]; //文件實際大小 (B) 30 UCHAR FileIdentifier[8]; //文件標誌 31 UCHAR FileNameLen; //文件名長度 32 UCHAR FileNameSpace; //文件名命名空間 33 //---- 0x52 --- 34 //FileName; // 文件名 (末尾填滿 8 字節) 35 UCHAR nextItemVCN[8]; // 下一項的 VCN (有子節點纔有) 36 };
A0H 屬性 $INDEX_ALLOCATION 索引分配屬性,也是索引,由屬性頭和運行列表組成,通常指向一個或多個目錄文件(INDX文件,即4K緩存);
A0H屬性和90H屬性共同描述了磁盤文件和目錄的 MFT 記錄的位置。第5項MFT的A0H屬性記錄根目錄的位置。
B0H 屬性 $BITMAP 位圖屬性,虛擬簇使用(佔用)狀況,這條屬性用在$MFT和索引中;在Bitmap文件中,每個 Bit 表明分區的一個簇,置1表明其已使用;
第0個字節的第0位表示分區第0簇,以後依次遞增。
C0H 屬性 $REPARSE_POINT 重解析點。使應用程序爲文件或目錄關聯一個應用程序數據塊,詳細略。
D0H $EA_INFORMATION 擴充信息屬性。爲在NTFS下實現HPFS的OS/2子系統信息,及WinNT服務器的OS/2客戶端應用而設置的,通常爲很是駐;
E0H $EA 擴充屬性 也是爲了實現NTFS下的 HPFS,通常爲很是駐;
100H $LOGGED_UTILITY_STREAM,EFS加密屬性,存儲用於實現EFS加密有關的信息,合法用戶列表,解密密鑰等等
(4) 解析一個磁盤分區的文件目錄的順序:
引導扇區($Boot) ----> 第0項記錄($MFT) ----> 根目錄記錄(第5項,90H,A0H) ----> 根目錄(INDX)
1 struct indxHeader // A0H外部緩存文件結構,最大長度通常爲4K 2 { 3 UCHAR mark[4]; // 標誌 "INDX" 4 UCHAR usnOffset[2]; // 更新序列偏移 5 UCHAR usnSize[2]; // 更新序列數組大小S 6 UCHAR LSN[8]; // 日誌文件序列號 7 UCHAR indxVCN[8]; // 本索引緩存在分配索引中的VCN 8 UCHAR itemOffset[4]; // 第一項索引的偏移(從這裏開始計算) 9 UCAHR itemSize[4]; // 索引項實際大小(B) 10 UCHAR itemAlloc[4]; // 索引項分配大小(B)(不包括頭部) 略小於4K 11 UCHAR isNode; // 是結點置1,表示有子節點 12 UCHAR noUse[3]; 13 //UCHAR USN[2S]; // 更新序列號和數組 14 };
在文件頭以後就是目錄項了,項的結構就是在上面90H的介紹裏定義的indexItem,每個項表明一個文件或目錄的MFT項,經過
項的 MFT 記錄號能夠計算出MFT項的磁盤地址,它等於$MFT 的偏移地址 + 編號*0x400,以此能夠找到該索引項對應的文件或子目錄
的MFT項。
(5) 搜索一個已刪除的文件或目錄的MFT項
上面說了,一個文件的MFT項的地址等於$MFT的地址+MFT編號*0x400,若是目錄中的對應項刪除了,那麼能夠從MFT的首部開始檢索,
由於MFT通常是連續的,而一個MFT項的大小又是固定的,一項項讀取,找到各自的0x30屬性,解析出文件名,進行比較 (MFT中有一些
空白區域須要跳過)。
(6) 關於文件名
通常在文件名的前一個字節是文件名的命名空間,不論是INDX文件中,仍是0x30屬性中。
0x00 ---- POSI ,最大的命名空間,大小寫敏感,支持除 '\0' 和 '/' 全部Unicode字符,最大程度255個字符;
0x01 ---- Win32,是POSI的子集,不支持字符:* / < > | \ : ? ,不能用句點或空格結束;
0x02 ---- DOS , 是Win32的子集,字符必須比空格0x20大,文件名1~8個字符,而後句點分割接後綴擴展名1~3個字符;
0x03 --- DOS&Win32,必須兼容Win32和DOS命名方式
在INDX文件中,常常能夠看到含有0x02和0x03或者0x01的兩個不一樣命名空間、相同MFT編號的項,也就是說這兩個目錄項指向同一個記錄,一樣的
在這個文件的MFT項中也有兩個0X30屬性,其中一個是0x01或0x03,表示的是完整的文件名;另外一個是0x02,DOS命名方式,它是一個短文件名,它在
咱們命名的基礎上,截斷 '.' 以前的超出6個字符的全部字符,只剩前6個,以後接上"~1" ,這樣正好8個字符,固然後面的句點和擴展名保留。另外,它必須
知足DOS命名規則,必須大寫,刪除禁止使用的字符等等。若是文件名重複了,在 "~1" 基礎上遞增,"~2","~3"等等。檢索比對時,咱們天然要使用前者。
(7) 關於字符集
字符集是字符在計算機上的編碼方式,能夠當作一種協議,一種約定規則,咱們處理一串二進制數所表明的字符時,必須清楚它用的是哪種編碼方式;
在windows系統中文件的命名是固定用兩個字節表示一個字符,在MFT中能夠發現英文文件名字符之間都填充一個 '\0' ,這是寬字符集與變長字符集兼容,
在寬字符集中,小於128的字符數值上是等於ASCII碼;咱們的文件數據通常用的是變長字符集(GB2312等等);
爲了比較輸入的文件名和NTFS中的文件名,咱們必需要先轉換;
兩個WinAPI 函數,用於寬字符和變長字符轉換
// 函數原型
int WideCharToMultiByte( UINT CodePage, // code page DWORD dwFlags, // performance and mapping flags LPCWSTR lpWideCharStr, // address of wide-character string int cchWideChar, // number of characters in string LPSTR lpMultiByteStr, // address of buffer for new string int cchMultiByte, // size of buffer LPCSTR lpDefaultChar, // address of default for unmappable // characters LPBOOL lpUsedDefaultChar // address of flag set when default // char. used ); int MultiByteToWideChar( UINT CodePage, // code page DWORD dwFlags, // character-type options LPCSTR lpMultiByteStr, // address of string to map int cchMultiByte, // number of bytes in string LPWSTR lpWideCharStr, // address of wide-character buffer int cchWideChar // size of buffer ); //--- WCHAR 定義在tchar.h中 ---- void charTest() { TCHAR tc1[16] ; //= _T("後來"); WCHAR tc2[8] = {0x540E, 0x6765, 0, 0, 0, 0, 0, 0}; // memset(tc2, 0, 20); // MultiByteToWideChar(CP_ACP, 0, tc1, 4, (LPWSTR)tc2, 4); WideCharToMultiByte(CP_ACP, 0 ,(WCHAR*)tc2, 2, tc1, sizeof(tc1), 0, 0); cout<<"tc1 "<<tc1<<sizeof(tc1)<<" "<<strlen(tc1)<<endl; PrintHex(tc1); cout<<endl; cout<<"tc2 "<<sizeof(tc2)<<" "<<wcslen((LPWSTR)tc2)<<endl; PrintHex(tc2); cout<<endl; }