[英]Python writing into a mapped file - strange behaviour
我有一个可以成功将二进制数据写入文件的 Python 脚本:
iterable_array = [i + 32 for i in range(50)]
file_handle = open("a.bin", "wb")
bytes_to_write = bytearray(iterable_array)
file_handle.write(bytes_to_write)
file_handle.close()
但是,我收到以下错误:
Traceback (most recent call last):
File "python_100_chars.py", line 20, in <module>
file_handle = open("a.bin", "wb")
OSError: [Errno 22] Invalid argument: 'a.bin'
当我在执行以下创建文件映射并在按键后读取数据的程序(源代码最初来自 Microsoft 文档)时尝试编写:
HANDLE hFile = CreateFileA( "a.bin",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = CreateFileMapping(
hFile, // use paging file
NULL, // default security
PAGE_EXECUTE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
_getch();
printf("string inside file:%s",(char *)((void *)pBuf));
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
我已经测试过我可以通过以下方式使用基本 I/O 写入内存映射文件(并查看结果):
HANDLE hFile = CreateFileA( "a.bin",
GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL ,
NULL);
char *p = "bonjour";
DWORD bw;
WriteFile( hFile,
p,
8,
&bw,
NULL);
感谢您的任何反馈!
我没有 Windows,所以我不能完全测试这种行为,但我相信这是因为 Windows 没有完全遵循 POSIX 语义,并且open(name, 'wb')
将不会截断现有文件,而是使用CREATE_ALWAYS
打开它会与另一个进程中映射的文件冲突。 ab
模式也可以工作,但是......正如Python 文档所说
'a'
用于附加(在某些 Unix 系统上,这意味着所有写入都附加到文件的末尾,而不管当前的查找位置)。
不幸的是, open
函数使用 C 语义作为标志,因此不可能将所需的模式指定为“打开文件以进行随机访问写入而不截断文件”,所以你能做的最好的事情就是“为两者打开它”在不截断文件的情况下读写”,这将是r+b
。
正如用户 Eryk Sun 指出的那样,问题是如果存在任何现有的内存映射,Windows 根本不支持文件截断:
如果调用
CreateFileMapping
为 hFile 创建文件映射对象,则必须先调用UnmapViewOfFile
取消映射所有视图,然后调用CloseHandle
关闭文件映射对象,然后才能调用SetEndOfFile
。
同样,没有比现有文件大的空间映射 - 如果映射长于文件大小,则文件被扩展......
在 POSIXly 正确的平台上,像这样的程序
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
struct stat s;
int fd = open("a.bin", O_RDWR);
fstat(fd, &s);
unsigned char *d = mmap(0, s.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
getchar();
for (int i = 0; i < s.st_size; i++) {
putchar(d[i]);
}
putchar('\n');
fflush(stdout);
getchar();
}
不会干扰运行上述 Python 程序。 但是,如果此 C 程序访问窗口内的文件,而该文件已被截断为 0,则会在 C 进程中引发 SIGBUS 信号。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.