20170514Windows05_异步IO操作
2017-05-15 22:50
78 查看
异步IO操作
封装File类:
1:CreateFile在FileAPI.h里面,CreateFile有宽窄字节之分。有CreateFileW和CreateFileA。宽字符处理在tchar.h库里面。2:CreateFile第二个参数指定打开文件的权限,如果使用GENERIC_ALL,打开的时候可能会失败,这样打开需要管理员权限。通常我们指定准确的权限比较好。
3:在文件打开之后,如果打开失败需要关闭句柄,可以将文件系统做成类的方式,析构就会自动释放。
4:tchar.h库里面有_t版本的字符串处理函数,他是自适应的,大多数都带有_s后缀的版本,他会指定长度,确保字符串操作的时候不会越界,其次可以保护我们的程序不会被别人使用shellcode注入,可能会被黑客利用这个漏洞。建议一直使用_s版本。
5:
#include <iostream> #include <windows.h> #include <tchar.h> #include <exception> //#include <FileAPI.h> class WindowException { public: WindowException(DWORD dwErrorCode) :m_dwErrorCode_(dwErrorCode) { FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, m_dwErrorCode_, 0, reinterpret_cast<LPWSTR>(&m_strErrorMsg_), 0, nullptr); } const TCHAR* what() const { return m_strErrorMsg_; } ~WindowException() { // LocalFree(m_strErrorMsg_); } private: DWORD m_dwErrorCode_; TCHAR* m_strErrorMsg_; }; class MyFile { public: MyFile(const TCHAR *strFilePath = TEXT("")) :m_hFile_(INVALID_HANDLE_VALUE) { SetPath(strFilePath); } ~MyFile() { if (m_hFile_ != INVALID_HANDLE_VALUE) CloseHandle(m_hFile_); delete m_strFilePath_; } BOOL OpenFile( _In_ DWORD dwDesiredAccess = GENERIC_READ|GENERIC_WRITE, _In_ DWORD dwShareMode = FILE_SHARE_READ, _In_ DWORD dwCreationDisposition = OPEN_EXISTING, _In_ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr, _In_opt_ HANDLE hTemplateFile = nullptr ) { BOOL bRet = TRUE; m_hFile_ = CreateFile(m_strFilePath_, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); if (m_hFile_ == INVALID_HANDLE_VALUE) { bRet = FALSE; throw WindowException(GetLastError()); } return bRet; } VOID SetPath(const TCHAR *strFilePath) { SIZE_T nstrlen = _tcslen(strFilePath) + sizeof(TCHAR); m_strFilePath_ = new TCHAR[nstrlen]; _tcscpy_s(m_strFilePath_, nstrlen, strFilePath); } const TCHAR* GetPath() { return m_strFilePath_; } protected: HANDLE m_hFile_; TCHAR *m_strFilePath_; }; int main() { try { MyFile clsFile; clsFile.SetPath(L"Demo.txt"); clsFile.OpenFile(); } catch (WindowException &e) { MessageBox(nullptr, e.what(), L"Error", MB_OK); } return 0; }
6:特别值得注意的是:异常类里面的指针,在throw的时候会被析构掉(VS2013编译器会,VS2015不会),catch的时候,catch的对象的这个指针指向的位置数据是错的。可以通过写上自己的拷贝构造函数来解决。
获取文件大小:
1:获取文件之后需要对文件进行操作,取文件的大小会涉及到两种大小。1:文件实际物理大小:
2:磁盘占用大小:
2:获取文件大小:GetFileSize和GetFileSizeEx。
1:GetFileSize:编的不可用了,因为他后面的长度过短,后面放的长度是32位的字节,小文件里面可用,大文件需要用64位。
2:GetFileSizeEx:能接受的大小事64位的数。
3:程序:
LARGE_INTEGER largeFileSize = { 0 }; GetFileSizeEx(clsFile.GetHandle(), &largeFileSize); std::cout << "FileSize:" << largeFileSize.QuadPart << std::endl; largeFileSize.LowPart = GetCompressedFileSize(clsFile.GetPath(), (LPDWORD)(&largeFileSize.HighPart)); std::cout << "FileCompressSize:" << largeFileSize.QuadPart << std::endl;
异步IO操作:
1:上面讲的都是同步IO,会产生阻塞,在读取文件的时候会导致卡死或者其他的。2:异步操作:必须确保CreateFile的时候设置了FILE_FLAG_OVERLAPPED标识符。设置了这个标识符,后面的同步IO操作就可能出错(读和写)。
3:文件操作:
1:ReadFile:读取文件。和下面的WriteFile都是同步操文件作。
2:WriteFile:写文件,特别注意,如果读取文件之后写文件,并不是从文件的末尾写,而是从读取到的位置的下一个位置开始写入。要在其他位置写入需要自己设定游标。
文件位置修改:
1:I/O操作的时候,CreateFile会在内核里面建立一个文件内核对象,ReadFile和WriteFile等都是通过文件内核对象对文件进行一系列的操作,操作的时候,比如ReadFile,文件里面肯定有一个标识位,记录我们读取到的位置(是一个偏移量),下次读取就是读取的这个位置之后的位置的数据。这个偏移量是基于某一个点的偏移量,如果我们要对这个偏移量进行操作,可以使用SetFilePointEx来进行操作。BOOL WINAPI SetFilePointerEx( _In_ HANDLE hFile, _In_ LARGE_INTEGER liDistanceToMove, _Out_opt_ PLARGE_INTEGER lpNewFilePointer, _In_ DWORD dwMoveMethod );
2:SetFilePointEx:
1:返回值:BOOL,
2:_In_ HANDLE hFile:要操作的文件的句柄
3:_In_ LARGE_INTEGER liDistanceToMove:要移动的byte个数,需要用LARGE_INTEGER来存储。
4:_Out_opt_ PLARGE_INTEGER lpNewFilePointer:用于接收移动后游标(记录)的位置。
5:_In_ DWORD dwMoveMethod:移动的相对位置,可设置为FILE_BEGIN,FILE_CURRENT,FILE_END三种。
3:在读取的时候,会涉及到上面的移动操作,但是在写的时候,可能会用到(并不是常用的)移动文件位置。需要设置文件尾,使用SetEndOfFile。
4:SetEndOfFile:只需传递一个参数,文件句柄,设置之后,文件尾就不再是原来的文件尾了,他会把当前设置的文件尾以后的数据去掉,会改变源文件的大小。
如果文件本身的大小只为24byte,我们使用SetFilePointEx该函数设置为1024方便我们读取和传输,我们可以和SetEndOfFile一起使用。在BT下载中,就是将文件设置为一块一块的,这样传输小文件,然后再组合起来会更快。
相关文章推荐
- 20170514Windows05_异步IO操作
- 20170514Windows05_异步IO操作
- 20170514Windows05_异步IO操作
- 20170514Windows05_异步IO操作
- 20170514Windows05_异步IO操作
- 20170514Windows05_异步IO操作
- 20170514Windows05_异步IO操作
- 20170514Windows05_异步IO操作
- 123-POSIX 异步IO(异步操作状态)
- 124-POSIX 异步IO(等待异步IO操作)
- python实现自己的异步IO等异步操作
- 125-POSIX 异步IO(取消操作)
- 关于异步IO与同步IO的写操作区别
- Windows编程_Lesson004_项目预备_异步IO操作(使用IOCP实现大文件拷贝的项目)
- Delphi编程实现Ping操作
- Java语言入门 -- 第九章 Java的输入输出操作
- Perl的文件操作(1)(适合初学者)
- Perl的文件操作(2)(适合初学者)
- 不刷新页面动态更新select选项,实现两个select相互操作
- SMTH Java FAQ (3) 文件与磁盘操作(菜鸟必看)