在这段代码中,我将一些文本写入内存映射文本文件。数据被成功写入文件,但是当我用记事本打开它时,在写入数据之后,“NULL”被重复写入映射的内存限制,该限制大于我写的文本。
可能的原因是什么?
pLogMsg = (char*)calloc(1024,sizeof(char));
printf("[INFO] entering logger writeback thread\n");
log_file = CreateFile (TEXT("one.txt"), // Open one.txt.
GENERIC_READ | GENERIC_WRITE, // Open for reading and writing
FILE_SHARE_WRITE, // file share
NULL, // No security
OPEN_ALWAYS, // Open or create
FILE_ATTRIBUTE_NORMAL, // Normal file
NULL); // No template file
if (log_file == INVALID_HANDLE_VALUE)
{
printf("%d [ERR] cant open file GLE %d\n",GetCurrentThreadId(),GetLastError());
return -1;
}
hMapping = CreateFileMapping( log_file, 0, PAGE_READWRITE, 0,4096 ,0 );
if (hMapping == INVALID_HANDLE_VALUE)
{
printf("%d [ERR] cant create file mapping %d\n",GetCurrentThreadId(),GetLastError());
return -1;
}
pFileData = (CHAR*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0,0, 0 );
if (pFileData == NULL)
{
printf("%d [ERR] cant mapview of file %d\n",GetCurrentThreadId(),GetLastError());
return -1;
}
pLogMsg = LogPrint();//returns a null terminated string
memcpy(pFileData,pLogMsg,strlen(pLogMsg));
pFileData += strlen(pLogMsg);
free(pLogMsg);
答案 0 :(得分:1)
文件中没有“文件结束”标记。您需要设置文件长度,以便操作系统正确标记它。
请参阅SetEndOfFile
的MSDN文档 Sets the physical file size for the specified file to the current position of the file pointer.
答案 1 :(得分:1)
您无法通过文件映射设置文件结束标记。文件结束标记实际上不存在于文件中。当读取超过文件末尾时,它是操作系统引发的标志。
要设置文件的大小,您必须在用于创建文件映射的文件对象上调用SetFilePointer,然后调用SetEndOfFile。
答案 2 :(得分:1)
首先CreateFileMapping
和MapViewOfFile
这是日志文件的错误解决方案。您需要使用FILE_APPEND_DATA
访问创建/打开文件而不是GENERIC_READ | GENERIC_WRITE
- 因此调用必须如下所示:
HANDLE log_file = CreateFileW(L"one.txt",
FILE_APPEND_DATA,
FILE_SHARE_WRITE|FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
在这种情况下,您使用FILE_APPEND_DATA
和SYNCHRONIZE
打开文件(因为没有FILE_FLAG_OVERLAPPED
):
如果来电者只设置 FILE_APPEND_DATA 和 SYNCHRONIZE 标志,那么 只能写入文件的末尾,以及任何偏移信息 关于对文件的写操作被忽略。该文件将 根据需要自动扩展此类操作。
之后你需要通过WriteFile
登录 - 它会自动附加到文件末尾。这就是日志文件的确切需要。
但是,如果要使用CreateFileMapping
和MapViewOfFile
- 首先CreateFileMapping
错误时返回0,请检查
if (hMapping == INVALID_HANDLE_VALUE)
错了
如果您想要更改文件大小 - 您需要使用SetFileInformationByHandle
FileEndOfFileInfo
(vista +)或NtSetInformationFile
FileEndOfFileInformation
(在任何地方工作,如何不难理解{ {1}}只是SetFileInformationByHandle
或NtSetInformationFile
上的非常薄的shell(在用户模式下,这是相同的功能))。使用ZwSetInformationFile
后跟SetFilePointer
也可能但不好而且没有效果 - 您将在src代码中进行2次调用而不是单次调用。在二进制文件中 - 你会遇到更糟糕的情况:首先设置文件位置,SetEndOfFile
读取此文件位置,最后用此位置调用SetEndOfFile
。所以3个电话而不是一个。并假设没有人在NtSetInformationFile
和SetFilePointer
电话
但需要明确了解只有在取消映射视图和关闭部分之后才能使用SetEndOfFile
调用SetFileInformationByHandle
。否则你会收到错误FileEndOfFileInfo
(ERROR_USER_MAPPED_FILE
)
如果调用 CreateFileMapping 来为其创建文件映射对象 首先必须调用hFile, UnmapViewOfFile 来取消所有视图的映射 调用 CloseHandle 来关闭文件映射对象,然后才能 致电 SetEndOfFile 。