文件系統是抽象的.是windows在軟件層面提供的一層虛擬的數據結構.編程
文件系統分爲NTFS 跟 FAT32. 具體看看二者的區別吧.windows
磁盤分區容量. api
單個文件容量. 意思就是一個文件能夠是多大的. NTFS 是能夠4G以上的大文件. FAT32則不能夠.緩存
EFS加密. 這個加密主要針對當前用戶的(例如Admins 管理員帳戶) 具體能夠 點擊一個文件. 文件->屬性 -> 高級 -> 加密保護文件內容.安全
若是在當前用戶則不會有什麼結果. 可是若是換了用戶訪問.則不能夠訪問這個加密文件了.數據結構
加密後的文件.app
文件顏色都會改變.異步
磁盤配額 意思就是能夠限制別的用戶訪問這個硬盤多少G內存. 函數
具體設置 xp下 盤符屬性-> 配額 學習
關於上面的講解咱們只須要了解便可.不深究.具體的的是學習API. API爲咱們封裝好了.咱們並不用關心NTFS 或者FAT32
標題中文件爲何添加了引號. 意思是不光能夠操做文件. 在windows系統中.一切東西都虛擬爲了文件. 例如管道 等等.. 均可以使用這些API.
api具體介紹
卷指的就是咱們的的邏輯硬盤. 例如C盤.
目錄則是C盤裏面的文件夾. 文件夾裏面可能仍是以文件夾. 也多是文件.
卷操做API 很簡單. 經常使用的就四個.
DWORD GetLogIcalDrives() 獲取卷 返回值是10進制.咱們須要轉化成16進制.而後轉換成二進制查看.每一位爲1表明有這個磁盤.不然則沒有
GetLogIcalDriveStrings(buffsize,buf) 獲取一個卷的盤符的字符串
GetDriveType(""目錄名稱") 獲取卷的類型
GetVolumeInformation() 獲取卷的類型
如如下代碼例子:
// A.cpp : 定義控制檯應用程序的入口點。 // #include "stdafx.h" #include <Windows.h> int main() { //1.獲取磁盤邏輯驅動卷 DWORD dwGetDrives = GetLogicalDrives(); /* 例如個人返回值是 252 轉化爲16進制 FC 轉化爲二進制 11111100 表明咱們有六個磁盤. CDEFGH 而個人剛好就是 CDEFGH 盤. */ //2.獲取磁盤卷字符串. TCHAR wszBuf[1024] = { NULL }; DWORD dwSize = sizeof(TCHAR) * 1024; GetLogicalDriveStringsW(dwSize, wszBuf); /* 邏輯驅動器返回後會存在wszBuf裏面. 本身作分割便可. 例如 C:\ B:\ */ //3.根據指定盤符獲取它的類型. 能夠移除的仍是不能夠移除的. DWORD dwDriveType = GetDriveTypeW(TEXT("C:\\")); //具體返回值查詢MSDN 注意從0開始 //4.獲取卷的詳細信息. DWORD dwVolumneSerial = 0; //驅動卷的序列號(不是硬盤序列號) DWORD dwFileMaxLen = 0; //系統容許的最大文件名的長度 DWORD dwFileSystem = 0; //文件系統標識. TCHAR dwFileSystemBuffer[255] = { 0 }; //文件操做系統的名稱 TCHAR szVolName[255] = { 0 }; //返回的卷的別名 GetVolumeInformationW( TEXT("c:\\"), // IN參數 你要查看那個卷的信息 szVolName, // OUT參數. 查詢到的卷的別名會給你.例如你的別名是C sizeof(TCHAR) * 255, // IN參數. 上面緩衝區的大小. &dwVolumneSerial, // OUT 驅動卷的序列號 &dwFileMaxLen, // OUT 寫文件讀文件等等文件名最大能夠是多大. &dwFileSystem, // OUT 文件操做系統標識.有多中宏組合,具體能夠查詢MSDN. 標識你這個文件是 dwFileSystemBuffer, //你當前系統是 NTFS 仍是FAT32 sizeof(TCHAR) * 255 //上面緩衝區的大小. ); return 0; }
CreateDirectory();//建立目錄
RemoveDirectory();//刪除目錄
MoveFile(); //修改目錄名稱.
GetCurrentDirectory(); //獲取進程當前目錄
SetCurrentDirectory(); //設置進程當前目錄.
具體代碼例子:
main函數調用便可.
void GetDirectoryApi() { CreateDirectory(TEXT("D:\\123"),NULL);//建立目錄 MoveFile(TEXT("D:\\123"), TEXT("D:\\456")); //修改目錄名稱. RemoveDirectory(TEXT("D:\\456"));//刪除目錄 TCHAR szCurrentDirectoryBuffer[255] = { 0 }; DWORD dwBuffsize = sizeof(TCHAR) * 255; GetCurrentDirectory(dwBuffsize, szCurrentDirectoryBuffer); //獲取當前目錄 SetCurrentDirectory(szCurrentDirectoryBuffer); //設置當前目錄. }
CreateFile( ) 建立文件
DeleteFile(); 刪除文件
CloseHandle(); 關閉文件句柄
GetFileSize(); 獲取文件大小.
ReadFile(); 讀文件
WriteFile(); 寫文件
CopyFile(); 拷貝文件
具體看以下代碼詳解參數意義.
void OptFileApi() { //1.建立文件 HANDLE hFile = CreateFile( TEXT("D:\\123.txt"), //你要建立的文件名 GENERIC_READ | GENERIC_WRITE, // 建立的這個文件只讀模式建立時只寫模式建立仍是讀寫均可以.若是隻讀則不能夠寫. 0, // 文件共享模式. 意思就是你這個文件建立完畢以後.當前讀寫只能有一我的在用,其餘人不能操做. 爲0就是排他. 或者說你能夠設置爲其餘人能夠讀. NULL, // 每一個內核對象都有的SD安全屬性 OPEN_EXISTING, //建立文件的信息. 你這個文件是文件不存在就建立 仍是打開已經存在的. 仍是老是建立新的. FILE_ATTRIBUTE_NORMAL, //建立的文件屬性. 意思就是我建立的這個文件是隱藏文件啊 仍是別的文件. 反正就是屬性. NULL ); //2.獲取文件大小 DWORD dwLowSize = 0; DWORD dwHighSize = 0; dwLowSize = GetFileSize(hFile, &dwHighSize); //若是是32位系統.返回值存儲了大小.若是是64位系統.則高32位也會存儲. //3.寫文件 TCHAR szBuffer[1024] =TEXT("HelloFile"); DWORD dwSize = sizeof(TCHAR) * 1024; DWORD OutSize = 0; WriteFile(hFile, //往哪一個文件中寫 szBuffer, //寫入的Buffer數據 dwSize, //寫入的大小 &OutSize, //實際寫入的大小.操做系統返回給你 NULL); //異步操做不須要 //4.讀文件 //4.1設置File讀取位置 SetFilePointer(hFile, //讀取那個文件 1, //低32位的偏移.具體偏移 就是從文件開始位置 + 偏移位置讀取. 若是是64位那麼第三個參數也要使用. 0, FILE_BEGIN //偏移起始位置. 文件開始 文件結束. 仍是文件中間 ); ReadFile(hFile, //讀哪一個 szBuffer, //讀入的數據放到Buffer dwSize, //Buffer大小 &OutSize, //實際讀入的大小.操做系統返回給你 NULL); //異步操做不須要 CloseHandle(hFile); //5.拷貝文件 CopyFile( TEXT("D:\\123.txt"), //源文件 TEXT("E:\\123.txt"), //目的文件 TRUE //是否覆蓋目的文件 ); //.關閉文件句柄 //6.刪除文件 DeleteFile(TEXT("d:\\123.txt")); }
咱們上幾篇博客講解了CreateFileMaping 建立物理內存頁. 那麼咱們能夠把文件跟物理頁綁定.
例以下圖:
其實文件映射到物理內存了.那麼咱們直接操做內存就能夠. 想至關於操做文件.
具體步驟.
1.建立文件.若是文件已經存在.則打開文件.獲取文件句柄.
2.申請共享內存.使用CreateFileMapping. 將文件句柄傳入.
3,將物理內存映射到線性地址(虛擬內存)中.使用 MapViewOfFile.
4.操做的虛擬地址就是文件內容了.
具體看以下代碼.
void OptFileApi() { //1.建立文件 HANDLE hFile = CreateFile( TEXT("D:\\calc.exe"), //你要建立的文件名 GENERIC_READ | GENERIC_WRITE, // 建立的這個文件只讀模式建立時只寫模式建立仍是讀寫均可以.若是隻讀則不能夠寫. 0, // 文件共享模式. 意思就是你這個文件建立完畢以後.當前讀寫只能有一我的在用,其餘人不能操做. 爲0就是排他. 或者說你能夠設置爲其餘人能夠讀. NULL, // 每一個內核對象都有的SD安全屬性 OPEN_EXISTING, //建立文件的信息. 你這個文件是文件不存在就建立 仍是打開已經存在的. 仍是老是建立新的. FILE_ATTRIBUTE_NORMAL, //建立的文件屬性. 意思就是我建立的這個文件是隱藏文件啊 仍是別的文件. 反正就是屬性. NULL ); //2.建立內存物理頁.跟文件掛靠 HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE,0, 0X1000, NULL); //讀寫的方式映射.不須要其它進程使用. //3.映射到虛擬內存位置. LPVOID szBuffer = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); //直接操做內存便可. printf("%x",*(PDWORD)szBuffer); //打印前四個字節. *(PDWORD)szBuffer = 0xFFFF0000; //修改文件前四個字節. /* 此API能夠 強制更新緩存. BOOL FlushViewOfFile( LPCVOID lpBaseAddress, // starting address SIZE_T dwNumberOfBytesToFlush // number of bytes in range); */ //4.取消映射 UnmapViewOfFile(szBuffer); CloseHandle(hFileMap); CloseHandle(hFile); }
若是映射到虛擬內存中.也就是調用完畢 MapViewOfFile的時候.其緩衝區就是文件的起始位置. 能夠直接指針修改了.
例如咱們的Calc計算器.頭四個字節已經被咱們修改爲了 0xFFFF了.
很簡單. 多動手作便可.
以下圖所示:
A進程映射物理內存.而且映射文件. B進程使用這塊物理內存其實也是操做文件.
只不過附帶了一個文件.修改修改物理內存的時候變成修改文件了.具體代碼不在貼了.
主須要申請共享內存的時候給定一個名字. 那麼雙進程就可使用了.
完整代碼
BOOL Characteristic(LPCTSTR lpFileName) { //打開文件,讀取頭八個字節. HANDLE hFile = CreateFile( lpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (INVALID_HANDLE_VALUE == hFile) return FALSE; //讀取文件特徵.這裏判斷是不是PE.讀取節個數.以及節開頭的標誌. HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0X1000, NULL); if (NULL == hFileMap) return FALSE; LPVOID szBuffer = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (NULL == szBuffer) return FALSE; UnmapViewOfFile(szBuffer); CloseHandle(hFileMap); CloseHandle(hFile); return 0; }