CreateFile、WriteFile、ReadFile
来源:互联网 发布:腾讯办公软件 编辑:程序博客网 时间:2024/05/21 03:57
读写文件每一个软件开发显目必定涉及的工作。CreateFile函数用于创建对应的文件句柄,WriteFile函数是用来写数据到文件,ReadFile函数是从文件里读取数据出来。
CreateFile
该函数用于生成设备(文件)的对应句柄(HANDLE)。
//CreateFile函数声明HANDLE CreateFile(LPCTSTP lpFileName, //文件名DWORD dwDesiredAccess, //访问方式DWORD dwShareMode, //共享模式LPSECURITY_ATTRIBUTES lpSecurityAttributes, //一个指向安全结构的指针,一般设置为NULL即可DWORD dwCreationDisposition, //创建方式 DWORD dwFlagAndAttributes, //属性HANDLE hTemplateFile //复制文件句柄)
下面是具体参数的相关说明
●dwDesiredAccess 访问方式
GENERIC_READ 表示允许对设备(文件)进行读访问
GENERIC_WRITE 表示允许对设备(文件)进行写操作
NULL 表示仅允许获取一个与设备(文件)有关的信息
●dwShareMode 共享模式
NULL 表示不共享
FILE_SHARE_READ 表示允许设备(文件)进行共享读访问
FILE_SHARE_WRITE 表示允许设备(文件)进行共享写访问
●lpSecurityAttributes 安全指针
指向一个 LPSECURITY_ATTRIBUTES 结构的指针,该结构定义了设备(文件)的安全特性,一般情况取NULL。
●dwCreationDisposition 创建方式
CREATE_NEW 创建文件,若文件存在则会出错
CREATE_ALWAYS 创建文件,会改写前一个文件(常用)
OPEN_EXISTING 文件必须已经存在,由设备提出要求
OPEN_ALWAYS 如果文件不存在则创建它
TRUNCATE_EXISTING 将现有文件缩短为零长度
●dwFlagAndAttributes 属性
FILE_ATTRIBUTE_ARCHIVE 将文件标记为归档属性
FLIE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认方式
FILE_ATTRIBUTE_NORMAL 默认属性
FIEL_ATTRIBUTE_HIDDEN 隐藏文件或目录
FIEL_ATTRIBUTE_READONLY 文件为只读文件
FIEL_ATTRIBUTE_SYSTEM 文件为只读文件
FILE_FLAG_WAITE_THROUGH 操作系统不得推迟对文件的写操作
FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作
FILE_FLAG_NO_BUFFERING 禁止对文件进行缓存处理,只能写入磁盘的扇区块
FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件进行优化
FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件进行缓冲优化
FILE_FLAG_DELETE_ON_CLOSE 关闭句柄后将文件删除,适用于临时文件
ReadFile
ReadFile函数将文件数据读取到一个缓冲区中。
//ReadFile 函数声明ReadFile( HANDLE hFile, //句柄 LPVOID lpBuffer, //缓冲区指针 DWORD nNumberOfBytesToRead, //读出的字节数 LPDWORD lpNumberOfBytesRead, //用于保存实际读出的字节数的存储区域,用于判断是否读取成功 LPOVERLAPPED lpOverlapped //OVERAPPED结构体指针,一般取NULL );
WriteFile
WriteFile函数将数据写入到一个文件中,该函数比fwrite更加灵活、方便、
//WriteFile 函数声明WriteFile( HANDLE hFile, //句柄 LPVOID lpBuffer, //数据缓冲区指针 DWORD nNumberOfBytesToRead, //写入的字节数 LPDWORD lpNumberOfBytesRead, //用于保存实际写入的字节数的存储区域,用于判断是否读取成功 LPOVERLAPPED lpOverlapped //OVERAPPED结构体指针,一般取NULL );
下面一起看一个借助这些WINAPI接口完成的有趣的示例,(该示例来自网易云课堂择善教育)
将文件隐藏于一个BMP文件中
首先先简单介绍一下BMP文件格式,是Windows操作系统中的标准图像文件格式
我们使用UItraEdit打开一个BMP文件可以看到如下结果:
我们先来看一下BMP文件首部的结构
typedef struct tagBITMAPFILEHEADER{ WORD bfType;//位图文件的类型,必须为BM(1-2字节) DWORD bfSize;//位图文件的大小,以字节为单位(3-6字节,低位在前) WORD bfReserved1;//位图文件保留字,必须为0(7-8字节) WORD bfReserved2;//位图文件保留字,必须为0(9-10字节) DWORD bfOffBits;//位图数据的起始位置,以相对于位图(11-14字节,低位在前) //文件头的偏移量表示,以字节为单位}BITMAPFILEHEADER;
这里最重要的就是需要获得位图的起始位置的偏移量,这样才能在不破坏原文件格式的情况下,将文件悄悄的写入。
对于每一个位图文件,第一个像素的偏移地址都是固定的,在上图最后一个红色方框处,00000036对应的就是首像素偏移字节量。
我们通过偏移量轻松的定位了第一个像素的位置,此时每一个数据由6个字节组成,反正就是后三个改了影响不大,很难看出来,所以可以藏数据(我想最强大脑那些人一定可以看出来吧)
不管了 ,下面一起看看代码,主要是文件读写操作。
// HideInBMP.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <windows.h> //winapi的头文件#include <iostream>#include <cstring>using namespace std;char * GetFileContent(char *filename, DWORD *filesize){//用于创建句柄,并开辟缓冲区,将文件内容读入 HANDLE hfile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); //文件句柄 //GENERIC_READ | GENERIC_WRITE 表示允许对文件进行读写操作 // FILE_SHARE_WRITE | FILE_SHARE_READ 表示允许对文件进行共享读写操作 //OPEN_EXISTING 表示文件必须已经存在 if (hfile==INVALID_HANDLE_VALUE) { cout << "Can't open " << filename << endl; return NULL; } DWORD dwRead; DWORD dwSize = GetFileSize(hfile, &dwRead); //读取文件大小 *filesize = dwSize; char * cBuf = new char[dwSize]; //在堆上开辟缓冲区,等待读入文件数据 RtlZeroMemory(cBuf, sizeof(cBuf)); //用0填充缓冲区 ReadFile(hfile, cBuf, dwSize, &dwRead, 0); //读入数据到缓冲区 if (dwRead != dwSize) //判断是否读入正常 { cout<<"Read"<<filename<<" failed\n"<<endl; return NULL; } CloseHandle(hfile); return cBuf; //返回指向缓冲区的指针}bool SaveFile(char * buf, int len, char * filename){//用于向BMP文件中写数据 HANDLE hfile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); //创建句柄 //允许读写操作 //允许共享读写操作 //若文件不存在则创建它,当我们要从BMP中解析出txt文件时是不存在的 ,(不过我感觉这里用CREATE_ALWAYS会不会也可以) //默认属性 if (hfile == INVALID_HANDLE_VALUE) { cout << "Can't open" << filename << endl; return false; } SetFilePointer(hfile, 0, 0, FILE_BEGIN); //将句柄指到文件首 DWORD dwWritten; //保存写了多少字节到文件中 WriteFile(hfile, buf, len, &dwWritten, 0); //将数据写入文件 CloseHandle(hfile); return true;}bool Hide(char *secretFileName,char *bmpFileName){ DWORD dwBMPSize, dwSecretSize; char * lpBMP = GetFileContent(bmpFileName, &dwBMPSize); //存储原始的文件名 char * lpSecret = GetFileContent(secretFileName, &dwSecretSize); DWORD * lpFirstPoint = (DWORD *)(lpBMP + 10); //读取第一个像素的偏移字节 char * lpCurrentBMP = lpBMP + *lpFirstPoint + 3; 将指针指向作用较小的后三个字节 char * lpCurrentSecret = lpSecret; //第一个像素点保存Secret文件大小 *((DWORD*)lpCurrentBMP) = dwSecretSize; //保存写入的TXT文件大小,解析时使用 lpCurrentBMP += 6; //每个像素占6个字节 for (; lpCurrentBMP<(lpBMP + dwBMPSize) && lpCurrentSecret <(lpSecret + dwSecretSize); lpCurrentBMP += 6) //不能大于bmp的大小 //循环将整个TXT文件依次写入缓冲区 { if (dwSecretSize>2) { *lpCurrentBMP = *lpCurrentSecret; *(lpCurrentBMP + 1) = *(lpCurrentSecret + 1); *(lpCurrentBMP + 2) = *(lpCurrentSecret + 2); lpCurrentSecret += 3; dwSecretSize -= 3; } else if(dwSecretSize==2) { *lpCurrentBMP = *lpCurrentSecret; *(lpCurrentBMP + 1) = *(lpCurrentSecret + 1); break; } else if (dwSecretSize==1) { *lpCurrentBMP = *lpCurrentSecret; break; } else { break; } } SaveFile(lpBMP, dwBMPSize, bmpFileName); //将写入了txt数据的缓冲区,写入bmp图片 delete[] lpBMP; delete[] lpSecret; return true;}bool Recovery(char *bmpFileName,char *secretFileName){//将保存了的TXT信息读出到缓冲区,操作与写入类似 DWORD dwBMPSize; char * lpBMP = GetFileContent(bmpFileName, &dwBMPSize); DWORD * lpFirstPoint = (DWORD *)(lpBMP + 10); cout << "First point offset : " << *lpFirstPoint << endl; DWORD dwSecretSize = *(DWORD *)(lpBMP + *lpFirstPoint + 3); //读取存储的TXT的文件大小 cout << dwSecretSize << endl; cout << "Secret file size : " << dwSecretSize << endl; char * SecretBuf = new char[dwSecretSize]; char * lpCurrentBMP = lpBMP + *lpFirstPoint + 3 + 6; for (int i = 0; lpCurrentBMP<(lpBMP + dwBMPSize) && i<dwSecretSize; lpCurrentBMP += 6) { SecretBuf[i] = *lpCurrentBMP; SecretBuf[i + 1] = *(lpCurrentBMP + 1); SecretBuf[i + 2] = *(lpCurrentBMP + 2); i += 3; } SaveFile(SecretBuf, dwSecretSize, secretFileName); delete[] SecretBuf; delete[] lpBMP; return true;}int main(int argc, char *argv[]){ if (argc<3) { cout << "Usage " << argv[0] << " Encrypt secret_file_name BMP_file_name"<<endl; cout << "Usage " << argv[0] << " Decrypt secret_file_name BMP_file_name" << endl; return 0; } if (strcmp(argv[1], "Encrypt") == 0) { Hide(argv[2], argv[3]); } else if (strcmp(argv[1],"Decrypt")==0) { Recovery(argv[3], argv[2]); } else { cout << argc << endl; cout << argv[1] << endl; cout << "Invalid para" << endl; } cout << "Done!" << endl; return 0;}
整个程序简单有趣,但将WINAPI文件读写的强大功能体现的淋漓尽致,相应的Win32控制台程序戳这里
http://download.csdn.net/detail/avalon_y/9532526
- CreateFile ReadFile WriteFile 详解
- CreateFile ReadFile WriteFile 详解
- CreateFile、WriteFile、ReadFile
- CreateFile,ReadFile,WriteFile,DeviceIoControl,CloseHandle
- CreateFile,ReadFile,WriteFile,DeviceIoControl,CloseHandle .
- CreateFile,ReadFile,WriteFile使用记录
- CreateFile WriteFile ReadFile FlushFileBuffers的基本用法
- CreateFile ReadFile WriteFile读写文件操作
- <Win32 API> 文件操作CreateFile/ReadFile/WriteFile
- win32 CreateFile readFile writefile 文件读写
- Windows API应用:CreateFile,WriteFile,ReadFile
- C/C++ 文件操作之CreateFile、ReadFile和WriteFile
- C/C++ 文件操作之CreateFile、ReadFile和WriteFile
- 使用CreateFile, ReadFile, WriteFile在Windows NT/2000/XP下读写绝对扇区的方法
- 使用CreateFile, ReadFile, WriteFile在Windows NT/2000/XP下读写绝对扇区的方法
- 使用CreateFile, ReadFile, WriteFile在Windows NT/2000/XP下读写绝对扇区的方法
- 请问怎么操作USB口,也是和串口一样用CreateFile,ReadFile,WriteFile等等吗?
- 使用API进行文件读写——CreateFile,ReadFile,WriteFile等
- KMP算法
- lua解析xml总结
- 麦肯锡七步成诗法学习笔记简记以及案例分析(附参考资料可下载)
- UGUI鼠标穿透UI问题的解决方法
- 对数组a中n个整数反序存放,可用指针实现。
- CreateFile、WriteFile、ReadFile
- Java 加密解密之对称加密算法PBE
- DHCP静态地址分配和ARP绑定的理解
- Lambda for Android
- Java Stream初探(二)
- NoHttp,volley,okhttp介绍
- bzoj2839 集合计数
- 1012. 数字分类 (20)
- string 类(刚做的一道题目,用到了string的排序)