【发布时间】:2017-07-15 15:13:32
【问题描述】:
我搜索了 MSDN,但没有找到任何关于与 WriteFile 和 ReadFile 共享同一个 HANDLE 的信息。注意:我没有使用create_always 标志,所以文件不可能被空文件替换。
我尝试使用相同 HANDLE 的原因是出于性能考虑。我的代码基本上是下载一些数据(写入文件),立即读取然后删除它。
在我看来,文件句柄只是一个内存地址,也是做 I/O 工作的入口。
错误是这样发生的:
CreateFile(OK) --> WriteFile(OK) --> GetFileSize(OK) --> ReadFile(Failed) --> CloseHandle(OK)
如果WriteFile调用了synchronized,这个ReadFile动作应该没有问题,即使WriteFile后的GetFileSize返回正确的值!!(新修改的文件大小),但事实是ReadFile读取的是修改前的值( lpNumberOfBytesRead 始终是旧值)。我突然想到一个想法,缓存!
然后我尝试了解更多关于我不知道的Windows File Caching 的信息。我什至尝试过 Flag FILE_FLAG_NO_BUFFERING 和 FlushFileBuffers 功能,但没有运气。当然我知道我可以在 WriteFile 和 ReadFile 之间再次执行 CloseHandle 和 CreateFile,我只是想知道是否有一些可能的方法可以在不再次调用 CreateFile 的情况下实现这一点?
上面是我的问题的最低限度,下面是我为这个概念制作的演示代码:
int main()
{
HANDLE hFile = CreateFile(L"C://temp//TEST.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL| FILE_FLAG_WRITE_THROUGH, NULL);
//step one write 12345 to file
std::string test = "12345";
char * pszOutBuffer;
pszOutBuffer = (char*)malloc(strlen(test.c_str()) + 1); //create buffer for 12345 plus a null ternimator
ZeroMemory(pszOutBuffer, strlen(test.c_str()) + 1); //replace null ternimator with 0
memcpy(pszOutBuffer, test.c_str(), strlen(test.c_str())); //copy 12345 to buffer
DWORD wmWritten;
WriteFile(hFile, pszOutBuffer, strlen(test.c_str()), &wmWritten, NULL); //write 12345 to file
//according to msdn this refresh the buffer
FlushFileBuffers(hFile);
std::cout << "bytes writen to file(num):"<< wmWritten << std::endl; //got output 5 here as expected, 5 bytes has bebn wrtten to file.
//step two getfilesize and read file
//get file size of C://temp//TEST.txt
DWORD dwFileSize = 0;
dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == INVALID_FILE_SIZE)
{
return -1; //unable to get filesize
}
std::cout << "GetFileSize result is:" << dwFileSize << std::endl; //got output 5 here as expected
char * bufFstream;
bufFstream = (char*)malloc(sizeof(char)*(dwFileSize + 1)); //create buffer with filesize & a null terminator
memset(bufFstream, 0, sizeof(char)*(dwFileSize + 1));
std::cout << "created a buffer for ReadFile with size:" << dwFileSize + 1 << std::endl; //got output 6 as expected here
if (bufFstream == NULL) {
return -1;//ERROR_MEMORY;
}
DWORD nRead = 0;
bool bBufResult = ReadFile(hFile, bufFstream, dwFileSize, &nRead, NULL); //dwFileSize is 5 here
if (!bBufResult) {
free(bufFstream);
return -1; //copy file into buffer failed
}
std::cout << "nRead is:" << nRead << std::endl; //!!!got nRead 0 here!!!? why?
CloseHandle(hFile);
free(pszOutBuffer);
free(bufFstream);
return 0;
}
那么输出是:
bytes writen to file(num):5
GetFileSize result is:5
created a buffer for ReadFile with size:6
nRead is:0
nRead 应该是 5 而不是 0。
【问题讨论】:
-
错误是什么?文件结束。为什么在这里问之前不检查错误代码。
-
@i486,我检查了,我不知道有文件结束问题。那个文件指针的概念以前在我的脑海中是不存在的。我为此付出了很大的努力,甚至写了一个测试代码并反复审查了近两天但仍然不明白,这让我非常沮丧。不管你说什么,我仍然接受所有批评,因为我是初学者。你不知道初学者遇到瓶颈时的感受,没有人愿意在这里发布愚蠢的问题来受到批评。作为一个初学者,我不认为这是愚蠢的,我尝试了很多,所以我问。
-
好的,但在 MSDN 中您可以阅读有关
ReadFile及其返回值的信息“如果函数失败,则返回值为零 (0)。要获取扩展错误信息,请调用 GetLastError”。然后检查GetLastError的值,看看有什么问题。
标签: c++ winapi readfile createfile writefile