文件系统是抽象的.是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; }