【发布时间】:2019-05-09 07:48:34
【问题描述】:
我经常使用File::Map 将特别小的文本文件映射到内存中,例如处理一些只读的正则表达式。现在我有一个用例,我还需要替换文件中的一些文本,并认为我仍然可以使用File::Map,因为它记录了以下内容:
文件被映射到一个变量,该变量可以像任何其他变量一样被读取,并且可以使用标准 Perl 技术(例如 regexps 和 substr)写入。
虽然我有兴趣替换的数据已在文件中正确替换,但我正在丢失数据,因为文件保持其原始大小并且数据最终被截断。新数据比旧数据大一点。这两件事都被警告,如使用以下句子记录:
不建议直接写入内存映射文件
将新值截断为内存映射的大小
对这两个警告的解释读起来就像一个人不应该使用File::Map 写任何东西,但它可能适用于可以处理截断文件或整体文件大小根本没有改变的情况。但是第一个引用明确提到支持写入,该规则没有任何例外。
那么,有没有一些特殊的方法可以安全地使用File::Map 编写,例如让基础文件增加等等?第一个警告使用directly 的措辞,我觉得还有其他更好的支持方式来编写?
我目前只是在映射视图上使用=~ s///,这似乎是错误的方法。我什至找不到任何人试图使用File::Map 编写代码,只有官方测试完全符合我的要求并期待我收到警告。此外,查看代码,似乎只有一个用例在其中写入根本不会导致警告,尽管我不明白我是如何触发它的:
static int mmap_write(pTHX_ SV* var, MAGIC* magic) {
struct mmap_info* info = (struct mmap_info*) magic->mg_ptr;
if (!SvOK(var))
mmap_fixup(aTHX_ var, info, NULL, 0);
else if (!SvPOK(var)) {
STRLEN len;
const char* string = SvPV(var, len);
mmap_fixup(aTHX_ var, info, string, len);
}
else if (SvPVX(var) != info->fake_address)
mmap_fixup(aTHX_ var, info, SvPVX(var), SvCUR(var));
else
SvPOK_only_UTF8(var);
return 0;
}
https://metacpan.org/source/LEONT/File-Map-0.55/lib/File/Map.xs#L240
毕竟,如果应该避免写作,为什么文档明确提到它是受支持的?如果它至少在所有情况下都导致警告,但我认为不支持。
【问题讨论】:
-
使用
File::Map和使用具有读写访问权限的文件句柄(例如,以+<模式打开)有什么区别?当您使用读写文件句柄时,您还必须注意不要破坏现有数据并在缩小文件时截断它,但有时它仍然有用。