Win32文件系統編程


            Win32文件系統編程

一丶了解什么是文件系統

  文件系統是抽象的.是windows在軟件層面提供的一層虛擬的數據結構.

文件系統分為NTFS 跟 FAT32. 具體看看兩者的區別吧.

磁盤分區容量. 

單個文件容量.  意思就是一個文件可以是多大的. NTFS 是可以4G以上的大文件. FAT32則不可以.

EFS加密.  這個加密主要針對當前用戶的(例如Admins 管理員賬戶)  具體可以 點擊一個文件. 文件->屬性 -> 高級 -> 加密保護文件內容.

如果在當前用戶則不會有什么結果. 但是如果換了用戶訪問.則不可以訪問這個加密文件了.

加密后的文件.

文件顏色都會改變.

 

磁盤配額  意思就是可以限制別的用戶訪問這個硬盤多少G內存. 

具體設置 xp下  盤符屬性-> 配額 

關於上面的講解我們只需要了解即可.不深究.具體的的是學習API. API為我們封裝好了.我們並不用關心NTFS 或者FAT32

 

二丶Windows提供的操作 "文件" 的 API

   標題中文件為什么添加了引號. 意思是不光可以操作文件. 在windows系統中.一切東西都虛擬為了文件. 例如管道 等等.. 都可以使用這些API.

api具體介紹

1.了解卷 文件 跟目錄的關系. 卷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;
}

2.文件夾(目錄) 操作的相關API

  

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); //設置當前目錄.
}

3.文件操作相關API

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進程使用這塊物理內存其實也是操作文件.

只不過附帶了一個文件.修改修改物理內存的時候變成修改文件了.具體代碼不在貼了.

主需要申請共享內存的時候給定一個名字. 那么雙進程就可以使用了.

 

完整代碼    

HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hFileMap = NULL;
LPVOID lpBase = NULL;

//1.打開文件以及獲取文件大小
hFile = CreateFile(
    TEXT("D:\\calc.exe"), 
    GENERIC_READ | GENERIC_WRITE, 
    0, 
    NULL, 
    OPEN_EXISTING, 
    FILE_ATTRIBUTE_NORMAL,
    NULL
    );

//2.創建內存物理頁.跟文件掛靠
hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0X1000, NULL); //讀寫的方式映射.不需要其它進程使用.
if (NULL == hFileMap)
{
    CloseHandle(hFile);
    return 0;
}

//3.映射到虛擬內存位置.
lpBase = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpBase == NULL)
{
    CloseHandle(hFileMap);
    CloseHandle(hFile);
    return 0;
}
//直接操作內存即可.
printf("%x", *(PDWORD)lpBase); //打印前四個字節.
*(PDWORD)lpBase = 0xFFFF0000; //修改文件前四個字節.
/*
此API可以 強制更新緩存.
BOOL FlushViewOfFile( LPCVOID lpBaseAddress, // starting address
SIZE_T dwNumberOfBytesToFlush // number of bytes in range);
*/
//4.取消映射
UnmapViewOfFile(lpBase);
CloseHandle(hFileMap);
CloseHandle(hFile);

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM