无缓冲区写文件
发布日期:2021-06-30 22:14:53 浏览次数:2 分类:技术文章

本文共 21512 字,大约阅读时间需要 71 分钟。

/*****************************************************************************/<2011_0725_0141>
无缓冲区写文件, 写文件完成后, 设置正确的FileTotalSize用无缓冲区写文件的目的: 某些程序会拦截, 替换fopen操作的文件内容, 应用层无法得到真实的文件数据, 这时需要用无缓冲区读写的方式来裸读.知识点: * CreateFile时带上标记FILE_FLAG_NO_BUFFERING* WriteFile时,需要写入扇区对齐或扇区倍数的块, 如果不够块大小, 在写入区先放着 在往写入区中写的时候, 不管是否写入了磁盘, 都需要自己维护写入的FileTotalSize 用来在文件完全写入后,设置正确的FileSize.* 用GetDiskFreeSpace来得到目标文件所在驱动器的扇区大小.* 为了提高写入速度, 应给出一个较大的缓冲区容量并按照扇区大小进行规约* 写入完成后, 关闭文件. 再打开文件, SetFilePointer, SetEndOfFile 设置文件的正确大小/*****************************************************************************/
// FileOPT.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include 
#include "helper/helper_file.h"USE_NAMESPACE_LSLS_RC BuildTestSrc(TCHAR * pcPathNameSrc, HANDLE & hFileSrc, BYTE* pucBufRd, size_t nSizeBufRd);int _tmain(int argc, _TCHAR* argv[]){ LS_RC lsRc = LS_RC_OK; BYTE ucBufRd[_MAX_PATH];//从其他地方读来的数据, 每次得到之后, 循环写入文件 PBYTE pucWriteNoCache = NULL;//以扇区倍数为单位写入块 DWORD dwRdBack = 0;//从其他地方读来的数据在ucBufRd中的字节数量 TAG_WIRTE_BUF_NO_CACHE_INFO sWriteBufNoCache;//无缓冲写入的结构, 用于带多个参数, 简化函数入参数量 DWORD dwWrBack = 0;//从其他地方读来的数据在ucBufRd中的字节数量 DWORD dwWirteBufLen = 0;//无缓冲方式要按照扇区写入, 一次性写入此扇区到文件 HANDLE hFileSrc = INVALID_HANDLE_VALUE;//从hFileSrc读内容 HANDLE hFileDst = INVALID_HANDLE_VALUE;//将读到的内容写到这里hFileDst TCHAR * pcPathNameDst = _T("c:\\tmp\\dir1\\dir2\\fileOptTest.txt");//要写入内容的文件 /** 假设写入的数据来源于磁盘上已经存在的文件 c:\\testForRd.txt, 这个文件的大小为 2345 */ TCHAR * pcPathNameSrc = _T("c:\\testForRd.txt"); lsRc = LsCreateFileEngrossNoCache(pcPathNameDst, hFileDst); if(LS_RC_OK != lsRc) { goto __tmain_END; } //得到无缓冲方式写时,以扇区倍数为大小的块长度 lsRc = LsGetWriteBufferLenForWirteFileNoCache(pcPathNameDst, sizeof(ucBufRd), dwWirteBufLen); if(LS_RC_OK != lsRc) { goto __tmain_END; } /** * 只开1个,2个扇区, 明显慢了, 120M的文件写完,超过了1分钟 * 按扇区倍数规约到1M, 试验表明, 10秒钟左右, 120M就写完了~ * 117 MB (123,456,789 字节) */ lsRc = LsGetSectorMultiple(1024 * 1024, dwWirteBufLen, dwWirteBufLen); if(LS_RC_OK != lsRc) { goto __tmain_END; } pucWriteNoCache = new BYTE[dwWirteBufLen];//按扇区倍数为单位的写入块 if(!pucWriteNoCache) { lsRc = MakeLsErrSn(LS_RC_MEMORY_ALLOC); goto __tmain_END; } //建立一个数据来源, 用于读取此数据来源写到pcPathNameDst lsRc = BuildTestSrc(pcPathNameSrc, hFileSrc, &ucBufRd[0], sizeof(ucBufRd)); lsRc = LsOpenFileForRead(pcPathNameSrc, hFileSrc); if(LS_RC_OK != lsRc) { goto __tmain_END; } //read src write to dst, write by no cache! ZeroMemory(&sWriteBufNoCache, sizeof(TAG_WIRTE_BUF_NO_CACHE_INFO)); sWriteBufNoCache.dwLenBufNoCache = dwWirteBufLen; sWriteBufNoCache.dwPosToWrite = 0;//由LsWriteFileNoCache决定 sWriteBufNoCache.hFileToWrite = hFileDst; sWriteBufNoCache.llTotalWriteIn = 0; sWriteBufNoCache.pBufNoCache = pucWriteNoCache; sWriteBufNoCache.pBufToWrite = ucBufRd; while(ReadFile(hFileSrc, ucBufRd, sizeof(ucBufRd), &dwRdBack, NULL)) { if(dwRdBack <= 0) { break;//已经读完了 } sWriteBufNoCache.dwLenToWrite = dwRdBack;//由ReadFile来决定 sWriteBufNoCache.dwLenWrBack = 0;//由LsWriteFileNoCache决定 lsRc = LsWriteFileNoCache(sWriteBufNoCache); if((LS_RC_OK != lsRc) || (dwRdBack != sWriteBufNoCache.dwLenWrBack)) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto __tmain_END; } } lsRc = LsWriteFileNoCache_FulshData(sWriteBufNoCache); if(LS_RC_OK != lsRc) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto __tmain_END; } LsCloseHandle(hFileDst); /** 在关闭文件后, 重新打开文件, 设置文件实际size */ lsRc = LsOpenFileForWrite(pcPathNameDst, hFileDst); if(LS_RC_OK != lsRc) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto __tmain_END; } lsRc = LsSetFilePointer(sWriteBufNoCache); if(LS_RC_OK != lsRc) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto __tmain_END; }__tmain_END: LsCloseHandle(hFileSrc); LsCloseHandle(hFileDst); LsDelete(pucWriteNoCache); if(LS_RC_OK == lsRc) { } else { _tprintf(_T("sir: some error was happen, please check the progam\n")); getchar(); } return 0;}LS_RC BuildTestSrc(TCHAR * pcPathNameSrc, HANDLE & hFileSrc, BYTE* pucBufRd, size_t nSizeBufRd){ LS_RC lsRc = LS_RC_OK; DWORD dwSizeRdBack = 27;//每次写入pcPathNameSrc的测试内容长度, 随便一个非特殊,非对齐的长度 DWORD dwSizeWrBack = 0;//每次写入pcPathNameSrc dwSizeRdBack长度后, 返回的写入长度 size_t nTotalWrite = 0;//总共写入的字节数 size_t n = 0; BOOL bStopWriteSrc = FALSE; LONGLONG llSizeWirteToSrc = 123456789;//写入pcPathNameSrc的测试内容总长度, 123456789是100多M的大小 lsRc = LsCreateFile(pcPathNameSrc, hFileSrc); if(LS_RC_OK != lsRc) { goto _BuildTestSrc_END; } for(n = 0; n < nSizeBufRd; n++) { *(pucBufRd + n) = (BYTE)(n % 0xff); } bStopWriteSrc = FALSE;//为最后一次写测试文件src准备的 while(llSizeWirteToSrc > 0) { if(llSizeWirteToSrc >= dwSizeRdBack) { llSizeWirteToSrc -= dwSizeRdBack; } else { dwSizeRdBack = (DWORD)llSizeWirteToSrc; bStopWriteSrc = TRUE; } if(!WriteFile(hFileSrc, pucBufRd, dwSizeRdBack, &dwSizeWrBack, NULL)) { //带缓冲方式写得时候, 不需要扇区对齐写, 写多少都是成功的, 且(dwSizeWrBack == dwSizeRdBack) lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto _BuildTestSrc_END; } nTotalWrite += dwSizeWrBack; if(dwSizeRdBack != dwSizeWrBack) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto _BuildTestSrc_END; } if(bStopWriteSrc) { break; } }_BuildTestSrc_END: LsCloseHandle(hFileSrc); return lsRc;}
/*** @file helper_file.h*/#ifndef _HELPER_FILE_H_#define _HELPER_FILE_H_#include "helper_common.h"#include "define/define_error.h"#include "define/define_struct_file.h"LS_NAMESPACE_BEGINLS_RC LsFindFile(CONST TCHAR * pcFileName);LS_RC LsCreateFile(TCHAR * pcFileName, HANDLE &hFile);				/**< 建立文件, 传出文件句柄 */LS_RC LsOpenFileForAppend(TCHAR * pcFileName, HANDLE &hFile);		/**< 打开现存文件去写, 传出文件句柄 */LS_RC LsOpenFileForRead(TCHAR * pcFileName, HANDLE &hFile);			/**< 打开现存文件去读, 传出文件句柄 */LS_RC LsOpenFileForWrite(TCHAR * pcFileName, HANDLE &hFile);		/**< 打开现存文件去写, 传出文件句柄 */LS_RC LsCloseHandle(HANDLE &hFile);			/**< 关闭文件件 */LS_RC LsDelete(PBYTE & pBuf);				/**< if (pBuf == TRUE), delete it */LS_RC LsWriteFile(HANDLE &hFile, LPCVOID pcBuf, DWORD dwSizeBuf);		/**< 写入文件内容 *//*WriteFile(hTempFile, buffer, dwBytesRead, &dwBytesWritten, NULL); *//** 独占方式文件操作 */LS_RC LsGetFullPathFromPathName(TCHAR * pcPathName, tstring & strPath);/**< 从全路径文件名中, 得到全路径 */LS_RC LsCreateFullPath(TCHAR * pcFullPath);/**< 建立给定的全路径目录 */LS_RC LsCreateFullPath(TCHAR * pcDriverName, std::vector
& vecPath);/**< 按照驱动器名称和目录的vector, 建立全路径目录 */LS_RC LsSplitPathToVector(TCHAR * pcFullPath, std::vector
& vecPath);LS_RC LsCreateFileEngrossNoCache(TCHAR * pcPathName, HANDLE & hFile); /**< 以独占无缓存方式建立文件 *//** * @fn LS_RC LsGetPathDiskInfo(TCHAR * pcPathName)* @brief 得到路径中的磁盘信息, 如果pcPathName是全路径文件名, 分解出路径作为查询条件*/LS_RC LsGetPathDiskInfo(TCHAR * pcPathName, TAG_PATH_INFO & pathInfo);/** 切分路径信息到pathInfo */LS_RC LsSplitPath(TCHAR * pcPathName, TAG_PATH_INFO & pathInfo);/** 从PcPathName中得到盘符, 查询磁盘空间, 填充DiskFreeSapce */LS_RC LsGetFreeDiskSapce(TCHAR * pcPathName, TAG_DISK_FREE_SPACE & DiskFreeSapce);/** 根据一次写入的最大字节数, 计算写缓冲区的大小* 独占无缓存方式写文件, 一次要写入磁盘扇区的倍数大小才能成功*/LS_RC LsGetWriteBufferLenForWirteFileNoCache(TCHAR * pcPathName, DWORD dwBytesOnceWriteMax, DWORD & dwWirteBufLen);/** 以扇区倍数为界限, 向给定容量规约 * 即取最靠近给定容量的扇区倍数的字节数*/LS_RC LsGetSectorMultiple(DWORD dwBytesUpperLimit, DWORD dwByteSectorBase, DWORD &dwSectorMultiple);/** 无缓冲方式的块写入 * 返回下一次写入的位置dwPosToWrite, 总共写入的字节数(用来写入完成后, 设置文件size)*/LS_RC LsWriteFileNoCache(TAG_WIRTE_BUF_NO_CACHE_INFO & sWriteBufNoCache);/** 最后一次的写, 然后调用关闭文件句柄 */LS_RC LsWriteFileNoCache_FulshData(TAG_WIRTE_BUF_NO_CACHE_INFO & sWriteBufNoCache);/** 设置文件指针 */LS_RC LsSetFilePointer(TAG_WIRTE_BUF_NO_CACHE_INFO & sWriteBufNoCache);/** 得Windows路径 */LS_RC LsGetWinOsPath(tstring & strPathName);LS_NAMESPACE_END#endif
/*** @file helper_flie.cpp*/#include 
#include "helper_string.h"#include "define/define_error.h"#include "helper/helper_file.h"LS_NAMESPACE_BEGINLS_RC LsFindFile(CONST TCHAR * pcFileName){ tstring::size_type nPos = 0; tstring::size_type nPosUnknown = -1; LS_RC lsRc = LS_RC_OK; WIN32_FIND_DATA FindFileData; HANDLE hFind; tstring strFileName; strFileName = pcFileName; nPos = strFileName.rfind(_T('\\')); if((nPosUnknown != nPos) && (_T('\\') == strFileName.at(strFileName.length() - 1))) { /** 要查找的文件不能带 "\\" */ strFileName.replace(nPos, 1, _T("\0")); } hFind = FindFirstFile(strFileName.c_str(), &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_NOT_FIND); goto _LsFindFile_END; } else { //_tprintf(_T("The first file found is %s\n"), FindFileData.cFileName); FindClose(hFind); }_LsFindFile_END: return lsRc;}LS_RC LsCreateFile(TCHAR * pcFileName, HANDLE &hFile){/** 建立文件传出文件指针 */ LS_RC lsRc = LS_RC_OK; hFile = CreateFile(pcFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(INVALID_HANDLE_VALUE == hFile) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_CREATE); goto _LsCreateFile_END; }_LsCreateFile_END: return lsRc;}LS_RC LsOpenFileForAppend(TCHAR * pcFileName, HANDLE &hFile){/** 建立文件传出文件指针 */ LS_RC lsRc = LS_RC_OK; LARGE_INTEGER FileSize; hFile = CreateFile(pcFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(INVALID_HANDLE_VALUE == hFile) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_OPEN); goto _LsOpenFileForAppend_END; } /** 如果是已经存在的日志文件, 移动到文件末尾, 形成附加日志的效果 */ if(GetFileSizeEx(hFile, &FileSize) && (FileSize.QuadPart > 0)) { //_llseek((HFILE)hFile, 0, SEEK_END);//这种用法有个警告 :( SetFilePointer(hFile, 0, NULL, FILE_END); }_LsOpenFileForAppend_END: return lsRc;}LS_RC LsOpenFileForRead(TCHAR * pcFileName, HANDLE &hFile){/** 建立文件传出文件指针 */ LS_RC lsRc = LS_RC_OK; hFile = CreateFile(pcFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(INVALID_HANDLE_VALUE == hFile) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_OPEN); goto _LsOpenFileForAppend_END; }_LsOpenFileForAppend_END: return lsRc;}LS_RC LsOpenFileForWrite(TCHAR * pcFileName, HANDLE &hFile){/**< 打开现存文件去写, 传出文件句柄 */ LS_RC lsRc = LS_RC_OK; hFile = CreateFile(pcFileName, GENERIC_READ | GENERIC_WRITE, NULL, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(INVALID_HANDLE_VALUE == hFile) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_OPEN); goto END; }END: return lsRc;}LS_RC LsWriteFile(HANDLE &hFile, LPCVOID pcBuf, DWORD dwSizeBuf){ LS_RC lsRc = LS_RC_OK; BOOL bWriteOK = TRUE; DWORD dwBytesWritten = 0; /**< 总共写入的字节数 */ DWORD dwBytesWrittenOnce = 0; /**< 一次写操作完成后, 已经写入的字节数 */ if(INVALID_HANDLE_VALUE == hFile) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_INVALID_HANDLE); goto _LsWriteFile_END; } do { bWriteOK = ::WriteFile(hFile, (PBYTE)pcBuf + dwBytesWritten, dwSizeBuf - dwBytesWritten, &dwBytesWrittenOnce, NULL); if(!bWriteOK) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto _LsWriteFile_END; } dwBytesWritten += dwBytesWrittenOnce; }while((dwSizeBuf - dwBytesWritten) > 0);_LsWriteFile_END: return lsRc;}LS_RC LsCloseHandle(HANDLE &hFile){ LS_RC lsRc = LS_RC_OK; BOOL bCloseOK = TRUE; if(INVALID_HANDLE_VALUE != hFile) { bCloseOK = CloseHandle(hFile); if(bCloseOK) { hFile = INVALID_HANDLE_VALUE; } else { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_CLOSE); goto _LsCloseFile_END; } }_LsCloseFile_END: return lsRc;}LS_RC LsDelete(PBYTE & pBuf){ if(pBuf) { delete pBuf; pBuf = NULL; } return LS_RC_OK;}LS_RC LsCreateFileEngrossNoCache(TCHAR * pcPathName, HANDLE & hFile){ LS_RC lsRc = LS_RC_OK; hFile = INVALID_HANDLE_VALUE; lsRc = LsCreateFullPath(pcPathName); if(LS_RC_OK != lsRc) { goto _LsCreateFileEngross_END; } hFile = CreateFile( pcPathName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_FLAG_NO_BUFFERING, NULL); if(INVALID_HANDLE_VALUE == hFile) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_CREATE); }_LsCreateFileEngross_END: return lsRc;}LS_RC LsGetPathDiskInfo(TCHAR * pcPathName, TAG_PATH_INFO & pathInfo){ LS_RC lsRc = LS_RC_OK; lsRc = LsSplitPath(pcPathName, pathInfo); if(LS_RC_OK != lsRc) { goto _LsGetPathDiskInfo_END; }_LsGetPathDiskInfo_END: return lsRc;}LS_RC LsSplitPath(TCHAR * pcPathName, TAG_PATH_INFO & pathInfo){ LS_RC lsRc = LS_RC_OK; if(!pathInfo.IsValid()) { lsRc = MakeLsErrSn(LS_RC_PARAM_STRUCT_INVALID); goto _LsSplitPath_END; } _tcscpy_s(pathInfo.PathInfo.path_buffer, SIZE_OF(pathInfo.PathInfo.path_buffer), pcPathName); _tsplitpath_s(pathInfo.PathInfo.path_buffer, pathInfo.PathInfo.drive, SIZE_OF(pathInfo.PathInfo.drive), pathInfo.PathInfo.dir, SIZE_OF(pathInfo.PathInfo.dir), pathInfo.PathInfo.fname, SIZE_OF(pathInfo.PathInfo.fname), pathInfo.PathInfo.ext, SIZE_OF(pathInfo.PathInfo.ext));_LsSplitPath_END: return lsRc;}LS_RC LsGetFreeDiskSapce(TCHAR * pcPathName, TAG_DISK_FREE_SPACE & DiskFreeSapce){ BOOL bRc = TRUE; LS_RC lsRc = LS_RC_OK; TAG_PATH_INFO pathInfo; ZeroMemory(&pathInfo, sizeof(TAG_PATH_INFO)); ZeroMemory(&DiskFreeSapce, sizeof(TAG_DISK_FREE_SPACE)); lsRc = LsSplitPath(pcPathName, pathInfo); if(LS_RC_OK != lsRc) { goto _LsGetFreeDiskSapce_END; } _tcscpy_s(DiskFreeSapce.DiskFreeSpace.cRootPathName, SIZE_OF(DiskFreeSapce.DiskFreeSpace.cRootPathName), pathInfo.PathInfo.drive); _tcscat_s(DiskFreeSapce.DiskFreeSpace.cRootPathName, SIZE_OF(DiskFreeSapce.DiskFreeSpace.cRootPathName), pathInfo.PathInfo.dir); /** 给定的全路径必须存在 */ lsRc = LsFindFile(DiskFreeSapce.DiskFreeSpace.cRootPathName); if(LS_RC_OK != lsRc) { goto _LsGetFreeDiskSapce_END; } bRc = GetDiskFreeSpace(DiskFreeSapce.DiskFreeSpace.cRootPathName, &DiskFreeSapce.DiskFreeSpace.dwSectorsPerCluster, &DiskFreeSapce.DiskFreeSpace.dwBytesPerSector, &DiskFreeSapce.DiskFreeSpace.dwNumberOfFreeClusters, &DiskFreeSapce.DiskFreeSpace.dwTotalNumberOfClusters); if(!bRc) { lsRc = MakeLsErrSn(LS_RC_GET_SYSTEM_INFO); goto _LsGetFreeDiskSapce_END; } bRc = GetDiskFreeSpaceEx(DiskFreeSapce.DiskFreeSpace.cRootPathName, &DiskFreeSapce.DiskFreeSpace.ullFreeBytesAvailable, &DiskFreeSapce.DiskFreeSpace.ullTotalNumberOfBytes, &DiskFreeSapce.DiskFreeSpace.ullTotalNumberOfFreeBytes); if(!bRc) { lsRc = MakeLsErrSn(LS_RC_GET_SYSTEM_INFO); goto _LsGetFreeDiskSapce_END; }_LsGetFreeDiskSapce_END: return lsRc;}LS_RC LsGetWriteBufferLenForWirteFileNoCache(TCHAR * pcPathName, DWORD dwBytesOnceWriteMax, DWORD & dwWirteBufLen){ LS_RC lsRc = LS_RC_OK; CONST DWORD dwInValid = -1; TAG_DISK_FREE_SPACE DiskFreeSpace; DWORD dwBytesPerSector = 0;/**< pcPathName所在磁盘每扇区size */ DWORD dwSectorCnt = 0;/**< 写nBytesOnceWriteMax所需的扇区数量 */ size_t nBytesModSector = 0;/**< 写nBytesOnceWriteMax所需的扇区数量之外的零头 */ if(dwInValid == dwBytesOnceWriteMax) { lsRc = MakeLsErrSn(LS_RC_PARAM_INVALID); goto _LsGetWriteBufferLenForWirteFileNoCache_END; } ZeroMemory(&DiskFreeSpace, sizeof(TAG_DISK_FREE_SPACE)); lsRc = LsGetFreeDiskSapce(pcPathName, DiskFreeSpace); if(LS_RC_OK != lsRc) { goto _LsGetWriteBufferLenForWirteFileNoCache_END; } dwBytesPerSector = DiskFreeSpace.DiskFreeSpace.dwBytesPerSector; nBytesModSector = dwBytesOnceWriteMax % dwBytesPerSector; dwSectorCnt = (dwBytesOnceWriteMax - nBytesModSector) / dwBytesPerSector; if(nBytesModSector > 0) { dwSectorCnt++; } dwWirteBufLen = dwBytesPerSector * dwSectorCnt;_LsGetWriteBufferLenForWirteFileNoCache_END: return lsRc;}LS_RC LsGetSectorMultiple(DWORD dwBytesUpperLimit, DWORD dwByteSectorBase, DWORD &dwSectorMultiple){ LS_RC lsRc = LS_RC_OK; DWORD dwMod = dwByteSectorBase % dwBytesUpperLimit; DWORD dwMultiple = (dwBytesUpperLimit - dwMod) / dwByteSectorBase; dwSectorMultiple = dwMultiple * dwByteSectorBase;END: return lsRc;}LS_RC LsGetWinOsPath(tstring & strPathName){ LS_RC lsRc = LS_RC_OK; TCHAR cInfoBuf[LS_INFO_BUFFER_SIZE]; ZeroMemory(cInfoBuf, sizeof(cInfoBuf)); if(!GetWindowsDirectory(cInfoBuf, LS_INFO_BUFFER_SIZE)) { lsRc = MakeLsErrSn(LS_RC_GET_SYSTEM_INFO); goto _LsGetWinOsPath_END; } strPathName = cInfoBuf;_LsGetWinOsPath_END: return lsRc;}LS_RC LsGetFullPathFromPathName(TCHAR * pcPathName, tstring & strPath){ /**< 从全路径文件名中, 得到全路径 */ LS_RC lsRc = LS_RC_OK; return lsRc;}LS_RC LsCreateFullPath(TCHAR * pcFullPath){ /**< 建立给定的全路径目录 */ LS_RC lsRc = LS_RC_OK; TAG_PATH_INFO pathInfo; tstring strFullPath; std::vector
vecPath; ZeroMemory(&pathInfo, sizeof(TAG_PATH_INFO)); lsRc = LsSplitPath(pcFullPath, pathInfo); if(LS_RC_OK != lsRc) { goto END; } /** 给出的磁盘名称必须是物理存在的, 这个不能手工建立 */ lsRc = LsFindFile(pathInfo.PathInfo.drive); if(LS_RC_OK != lsRc) { goto END; } /** 如果全路径已经存在, 不再去分析, 建立全路径 */ strFullPath = pathInfo.PathInfo.drive; strFullPath += _T('\\'); strFullPath += pathInfo.PathInfo.dir; lsRc = LsFindFile(strFullPath.c_str()); if(LS_RC_OK == lsRc) { goto END; } /** 切分全路径到vector */ lsRc = LsSplitPathToVector(pathInfo.PathInfo.dir, vecPath); if(LS_RC_OK != lsRc) { goto END; } /** 建立多级目录 */ lsRc = LsCreateFullPath(pathInfo.PathInfo.drive, vecPath); if(LS_RC_OK != lsRc) { goto END; }END: return lsRc;}LS_RC LsCreateFullPath(TCHAR * pcDriverName, std::vector
& vecPath){ INT iRc = 0; INT iLastErr = 0; LS_RC lsRc = LS_RC_OK; tstring strDir = pcDriverName; std::vector
::iterator it = vecPath.begin(); for(it = vecPath.begin(); it != vecPath.end(); it++) { if(_T('\\') != strDir.at(strDir.length() - 1)) { strDir += '\\'; } strDir += *it; iRc = _tmkdir(strDir.c_str()); //_tmkdir返回的东西不对啊, 和MSDN上说得不一样, 先忽略// iLastErr = GetLastError();// if((0 != iRc) && (EEXIST != GetLastError()))// {// lsRc = MakeLsErrSn(LS_RC_ERR_FILE_CREATE);// goto _LsCreateFullPath_pcDriverName_vecPath_END;// } /** 换种方法判断是否建立文件夹成功, 原来就存在, 也算成功 */ lsRc = LsFindFile(strDir.c_str()); if(LS_RC_OK != lsRc) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_CREATE); goto END; } }END: return lsRc;}LS_RC LsSplitPathToVector(TCHAR * pcFullPath, std::vector
& vecPath){ LS_RC lsRc = LS_RC_OK; tstring strFullPath = pcFullPath; tstring strSubDirName = _T(""); size_t nPosFind = 0; size_t nPosBegin = -1; size_t nPosEnd = -1; size_t nSize = _tcslen(strFullPath.c_str()); do { nPosFind = strFullPath.find(_T('\\'), nPosFind); if(nPosFind != -1) { nPosBegin = nPosEnd; nPosEnd = nPosFind; if((nPosBegin != nPosEnd) && (-1 != nPosBegin) && (-1 != nPosEnd) && (nPosEnd > nPosBegin)) { strSubDirName = strFullPath.substr(nPosBegin + 1, nPosEnd - nPosBegin - 1); vecPath.push_back(strSubDirName.c_str()); } } nPosFind++; } while((nPosFind != -1) && (nPosFind < nSize)); return lsRc;}LS_RC LsWriteFileNoCache(TAG_WIRTE_BUF_NO_CACHE_INFO & sWriteBufNoCache){ LS_RC lsRc = LS_RC_OK; DWORD dwLenWriteOnce = 0; DWORD dwLenWriteBack = 0; DWORD dwPosToWriteSrc = 0;//源缓冲区要写入到块的位置 //如果要写入的长度 + 块写入当前位置 >= 无缓冲写入块长度, 向文件中循环写入块 while((sWriteBufNoCache.dwLenToWrite + sWriteBufNoCache.dwPosToWrite) >= sWriteBufNoCache.dwLenBufNoCache) { dwLenWriteOnce = sWriteBufNoCache.dwLenBufNoCache - sWriteBufNoCache.dwPosToWrite; memcpy(sWriteBufNoCache.pBufNoCache + sWriteBufNoCache.dwPosToWrite, sWriteBufNoCache.pBufToWrite, dwLenWriteOnce); dwPosToWriteSrc += dwLenWriteOnce; sWriteBufNoCache.dwLenToWrite -= dwLenWriteOnce; sWriteBufNoCache.dwPosToWrite = 0; if(!WriteFile(sWriteBufNoCache.hFileToWrite, sWriteBufNoCache.pBufNoCache, sWriteBufNoCache.dwLenBufNoCache, &dwLenWriteBack, NULL)) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto END; } /** 将数据写进文件, 要不一个空文件摆在那半天没动静, 像挂掉了一样 */ if(!FlushFileBuffers(sWriteBufNoCache.hFileToWrite)) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto END; } sWriteBufNoCache.dwLenWrBack += dwLenWriteOnce; sWriteBufNoCache.llTotalWriteIn += dwLenWriteOnce; } //移动不足一块的数据到写入块, 更新给调用者的回答 memcpy(sWriteBufNoCache.pBufNoCache + sWriteBufNoCache.dwPosToWrite, sWriteBufNoCache.pBufToWrite + dwPosToWriteSrc, sWriteBufNoCache.dwLenToWrite); sWriteBufNoCache.dwPosToWrite += sWriteBufNoCache.dwLenToWrite; //更新无缓冲块当前写入位置, 用于下次写入 sWriteBufNoCache.dwLenWrBack += sWriteBufNoCache.dwLenToWrite; //更新调用者本次调用写入数量 sWriteBufNoCache.llTotalWriteIn += sWriteBufNoCache.dwLenToWrite; //更新总写入数量, 用于确定文件总SizeEND: return lsRc;}/** 最后一次的写, 然后调用关闭文件句柄 */LS_RC LsWriteFileNoCache_FulshData(TAG_WIRTE_BUF_NO_CACHE_INFO & sWriteBufNoCache){ LS_RC lsRc = LS_RC_OK; DWORD dwLenWriteOnce = 0; DWORD dwLenWriteBack = 0; dwLenWriteOnce = sWriteBufNoCache.dwLenBufNoCache - sWriteBufNoCache.dwPosToWrite; if(dwLenWriteOnce > 0) { sWriteBufNoCache.dwPosToWrite = 0; if(!WriteFile(sWriteBufNoCache.hFileToWrite, sWriteBufNoCache.pBufNoCache, sWriteBufNoCache.dwLenBufNoCache, &dwLenWriteBack, NULL)) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto END; } sWriteBufNoCache.dwLenWrBack += dwLenWriteOnce; /** * 在LsWriteFileNoCache中, 已经对每次写入的字节数做了回应, 已经是正确的总长度, * 最后一次写入不再更新 sWriteBufNoCache.llTotalWriteIn */ //sWriteBufNoCache.llTotalWriteIn += dwLenWriteOnce; }END: return lsRc;}LS_RC LsSetFilePointer(TAG_WIRTE_BUF_NO_CACHE_INFO & sWriteBufNoCache){ LS_RC lsRc = LS_RC_OK; //LONG_MAX 0x7fffffff long LONG lDistanceToMove = (LONG)(sWriteBufNoCache.llTotalWriteIn & LONG_MAX); LONG lDistanceToMoveHigh = (LONG)(sWriteBufNoCache.llTotalWriteIn >> 31); LONGLONG ullFileSize = sWriteBufNoCache.llTotalWriteIn; if(INVALID_SET_FILE_POINTER == SetFilePointer(sWriteBufNoCache.hFileToWrite, lDistanceToMove, &lDistanceToMoveHigh, FILE_BEGIN)) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto END; } if(!SetEndOfFile(sWriteBufNoCache.hFileToWrite)) { lsRc = MakeLsErrSn(LS_RC_ERR_FILE_WRITE); goto END; }END: return lsRc;}LS_NAMESPACE_END
还没有封装成类, 不是很好用.

demo上传位置:  FileOptNoCache_V2011_0725_0202.rar

http://download.csdn.net/source/3466635

<2011_0801>

遇到了奇怪问题,无缓冲区读文件时总是失败. 最后发现, 无缓冲区读,也是要读扇区倍数的字节数.  用无缓冲区方法写文件时,写完扇区倍数字节完成后,因为文件一般都不是扇区倍数字节的,最后要用SetFilePointer和EndOfFile来确定正确的文件Size. 读这种带零头的文件时,实际操作时怎样的呢?  有时间再做实验。 无缓冲区读写,不知道什么样的实际场景非要使用无缓冲区读写。 真不方便。

转载地址:https://lostspeed.blog.csdn.net/article/details/6630555 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:实验: VS2005远程调试
下一篇:goto and lable

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月10日 23时25分46秒