【发布时间】:2021-01-30 00:11:29
【问题描述】:
作为我学习 Win32 的一部分,我创建了一个简单的程序,它写入一个名为 file1.txt 的现有文件,然后从该文件读取缓冲区并在控制台上显示缓冲区。文件内容以Hello 开头。该问题将在代码之后讨论。这是代码(在 Visual Studio 2017 上用 C++/Win32 编写):
#include <iostream>
#include <tchar.h>
#include <Windows.h>
#define UNICODE
#define _UNICODE
using namespace std;
int _tmain(int _argc, TCHAR *_argv[])
{
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(sa);
sa.bInheritHandle = false;
sa.lpSecurityDescriptor = NULL;
HANDLE hFile = CreateFile(L"file1.txt", GENERIC_READ | GENERIC_WRITE, 0, &sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
LARGE_INTEGER size, physize;
DWORD fptr = 0;
BYTE buff[] = " World";
if (hFile == INVALID_HANDLE_VALUE)
{
cout << "Error: " << GetLastError() << "\n";
return -1;
}
cout << "File created!\n";
GetFileSizeEx(hFile, &size);
cout << "File Size: " << size.QuadPart << "\n";
physize.LowPart = GetCompressedFileSize(L"File1.txt", (LPDWORD)&physize.HighPart);
cout << "Physical Size: " << physize.QuadPart << "\n";
SetFilePointer(hFile, 0, (PLONG)&fptr, FILE_END);
WriteFile(hFile, buff, (DWORD)strlen((const char *)buff), &fptr, NULL);
WaitForSingleObject(hFile, INFINITE);
SetFilePointer(hFile, 0, (PLONG)&fptr, FILE_BEGIN);
GetFileSizeEx(hFile, &size);
cout << "Size now is: " << size.QuadPart << "\n";
BYTE *buff2 = new BYTE[size.QuadPart + 1];
buff2[size.QuadPart] = '\0';
if (!ReadFile(hFile, (LPVOID)buff2, size.QuadPart, &fptr, NULL))
{
cout << "Error: " << GetLastError() << "\n";
return -1;
}
cout << buff2 << "\n";
CloseHandle(hFile);
delete[] buff2, buff;
return 0;
}
写入后,文件内容为Hello World。但是控制台中的输出是:
File created!
File Size: 5
Physical Size: 5
Size now is: 11
═══════════
我搜索了网络,甚至搜索了这个网站,但没有找到任何对我有帮助的解决方案。在我看来,问题出在阅读上,因为写作已经成功完成。我什至使用函数WaitForSignalObject 来确保写作结束。有什么我错过的吗?谢谢你的帮助。
附:我的朋友已被禁止在此网站提问,他可以做些什么来解除禁令并继续使用该网站?
P.S.2 如果有任何语法错误,我很抱歉,英语不是我的母语。
【问题讨论】:
-
WaitForSingleObject是干什么用的? -
@jab 可以等待文件句柄(与任何其他内核对象句柄一样)。尽管几乎没有人这样做,因为文件句柄何时发出信号的语义通常与开发人员的需求(或期望)不一致。
-
@IInspectable,并非所有内核对象类型都是可等待的——只有支持
SYNCHRONIZE访问的类型。最常见的类型是可等待的,包括 File 对象,但也有一些不是,例如 Key、Token、Section、WindowStation 和 Desktop。也就是说,对以同步模式打开的文件调用WaitForSingleObject毫无意义。 I/O 管理器本身会等待一个同步的 File 对象来完成 I/O 请求,因此WriteFile在写入完成之前不会返回。 -
你永远不会检查寻找开始是否失败。为什么选择 SECURITY_ATTRIBUTES?压缩后的大小无关紧要。你定义 UNICODE 太晚了。
标签: c++ windows visual-studio file winapi