如何实现跨平台独立文件处理及共享选项?遗留代码适配咨询
这个问题问到点子上了——标准C++确实没有直接对应_SH_DENYNO的跨平台API,不过咱们有几种可靠的方案来实现跨平台的文件共享访问,我来给你拆解清楚:
_SH_DENYNO到底是什么? 先明确下概念:_SH_DENYNO是Windows特有的文件共享标志,直白点说就是允许其他进程同时读写这个已打开的文件——不会像_SH_DENYRW那样拒绝其他进程的访问请求。你之前用的_sopen和VS扩展的std::ifstream构造函数,本质都是在Windows平台上设置这个共享规则。
遗憾的是,标准C++的iostream库(包括std::ifstream)并没有暴露文件共享模式的设置接口。这是因为标准库要兼顾跨平台性,把操作系统层面的文件权限、共享这类细节都做了抽象,所以没有统一的标准API来实现_SH_DENYNO的效果。
方案1:条件编译+平台特定实现
这是最常用、最可控的跨平台写法,针对不同操作系统分别处理:
- Windows平台:你提到的VS2019的
std::ifstream扩展构造函数完全可以用,因为ios_base::_Openprot本身就等价于_SH_DENYNO,直接传第三个参数或者用默认值都能达到效果。如果想更明确,也可以直接写_SH_DENYNO:
要是你想用C++17及以后更标准的写法,还可以先调用Win32 API的std::ifstream file(filepath, std::ios::in, _SH_DENYNO);CreateFile获取文件句柄(明确指定FILE_SHARE_READ | FILE_SHARE_WRITE,这就是_SH_DENYNO的底层逻辑),再把句柄关联到std::filebuf:#include <fstream> #include <windows.h> std::ifstream open_shared_file(const char* filepath) { HANDLE hFile = CreateFileA( filepath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, // 对应_SH_DENYNO的共享规则 nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr ); std::ifstream file; if (hFile != INVALID_HANDLE_VALUE) { std::filebuf fb; fb.open_handle(reinterpret_cast<intptr_t>(hFile), std::ios::in); file.rdbuf(&fb); } return file; } - POSIX平台(Linux/macOS等):这里反而简单——POSIX系统默认允许多个进程同时打开同一个文件进行读写(只要文件权限设置允许),所以直接用标准的
std::ifstream打开就自动满足_SH_DENYNO的需求,不需要额外设置:std::ifstream file(filepath, std::ios::in);
把这些逻辑用条件编译包起来,就能写出跨平台的代码了。
方案2:借助第三方跨平台库
如果你不想自己维护平台特定的代码,也可以用成熟的第三方库,比如Boost.Iostreams或Boost.FileSystem。这些库封装了不同平台的文件操作细节,能直接设置文件共享模式,不用你自己写#ifdef判断。比如Boost的stream可以通过指定open_mode来设置共享选项,用法和标准iostream类似,但更灵活。
标准C++没有统一的方式来设置_SH_DENYNO这类文件共享模式,因为这属于操作系统的特有特性。最靠谱的跨平台方案要么是自己用条件编译分平台实现,要么是借助第三方库来简化开发。
内容的提问来源于stack exchange,提问作者Build Succeeded

