当我使用ifstream打开文件时,如何分享文件删除权限?

5

我希望能够创建一个文件,在使用ifstream打开后可以被删除。

我知道在使用Windows API的CreateFile时很容易实现这一点。

CreateFile(...,FILE_SHARE_DELETE,...)

但是当我使用 ifstream 打开文件进行测试时,它无法被删除。

我没有找到任何关于在 ifstream 上设置类似 FILE_SHARE_DELETE 的属性的文档。

我该如何解决这个问题?


5
你无法以可移植的方式实现。 - πάντα ῥεῖ
1
如果我需要的话,我想我会寻找打开具有现有C FILE句柄或文件号的ifstream的方法,这将对应于API级别的句柄。也许。 - Cheers and hth. - Alf
2
一些编译器(例如GCC)将即将成为标准的文件系统库作为“技术规范”提供。您可以使用:std::experimental::filesystem::remove。否则,boost中有相同(或类似)的库。 - Galik
2
@Galik 这与 FILE_SHARE_DELETE 无关。 - David Heffernan
1
有关Alf的建议,请参见https://dev59.com/cHRB5IYBdhLWcg3w4bOv。 - andlabs
1
最后,我尝试了Alf的建议,它运行良好。感谢您的帮助。 - Min Mun
2个回答

5

Visual Studio 版本的 std::ifstream 有一个非标准构造函数和一个非标准的 open() 重载,均带有一个额外的可选参数 _Prot,用于指定“文件保护/共享标志”(有关可用标志的列表,请参见 _fsopen())。然而,不支持 "delete" 共享。

不过,这里有个替代方案。Visual Studio 版本的 std::ifstreamstd::ofstream 都有非标准构造函数,接受一个 FILE* 作为文件访问参数。例如,您可以使用 Microsoft 的 _open_osfhandle()_fdopen() 函数将来自 CreateFile()HANDLE 包装成 FILE*(出于简洁起见已删除错误处理):

Can I use CreateFile, but force the handle into a std::ofstream?

HANDLE file_handle = CreateFile(...,FILE_SHARE_DELETE,...);
int file_descriptor = _open_osfhandle((intptr_t)file_handle, _O_RDONLY);
FILE* file = _fdopen(file_descriptor, "r");
std::ifstream stream(file);
...
// Closes stream, file, file_descriptor, and file_handle.
stream.close();

如果您需要更便携的非Microsoft编译器,您可能需要编写一个自定义的std::basic_streambuf类(或者从std::filebuf派生),以包装您的HANDLE,然后直接将该类的对象传递给std::basic_istream构造函数。


这个比被接受的答案简单易懂。 - Mohan Kumar

2
文件权限因操作系统而异:

整个文件的读、写或删除访问共享

在父目录上具有写入和执行权限。文件本身的权限是无关紧要的

由于Windows是唯一具有删除访问权限的系统,并且已经以CreateFile with FILE_SHARE_DELETE的形式提供了自己的访问器,因此没有动机将此功能标准化。

如果此功能对您的程序至关重要,则可以实现此跨平台函数(请注意,根据文件大小,这可能非常昂贵):

  1. 使用fstream打开文件进行读写;如果失败,则表示该文件已被其他程序锁定,无法删除。
  2. 将文件读入内存
  3. 关闭文件
  4. 删除文件;如果失败,则表示您没有文件的删除权限。
  5. 使用ofstream重新打开文件进行写操作。
  6. 将内存中的数据写回到ofstream
  7. 返回ofstream
只要返回的ofstream处于打开状态,操作系统就会负责防止更改文件或其所在目录的权限。因此,由于您已经删除了文件,所以当关闭ofstream时,您仍然可以删除该文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接