C++:以非独占模式打开文件

6
我需要开发一个应用程序,它可以解析日志文件并将特定数据发送到服务器。该应用程序需要在Linux和Windows上运行。
当我想要测试日志滚动系统(将“.1”附加到已创建文件的名称,并创建具有相同名称的新文件)时,问题出现了。在Windows上(尚未在Linux上进行测试),即使我以“输入模式”(ios :: in)打开std :: ifstream()中的文件(独占访问?),也无法重命名该文件。
是否有一种跨平台的方式以非独占方式打开文件?
5个回答

3
有没有一种非排他性打开文件的方式?
是的,在使用Win32时,可以将各种FILE_SHARE_Xxxx标志传递给CreateFile。
这是跨平台的吗?
不,它需要特定于平台的代码。
由于令人讨厌的向后兼容性问题(DOS应用程序是单任务的,假设没有任何东西可以在它们下面删除文件,即它们可以fclose()然后fopen()而不会出现任何问题;Win16保留了此假设以使移植DOS应用程序更加容易,Win32保留了此假设以使移植Win16应用程序更加容易,这很糟糕),Windows默认以排他方式打开文件。
底层操作系统基础结构支持删除/重命名打开的文件(尽管我认为它确实有限制,即内存映射文件不能被删除,我认为这不是在*nix上找到的限制),但默认的打开语义不支持。
C++没有任何关于这个的概念;C++操作环境与DOS操作环境大致相同--没有其他应用程序同时运行,因此不需要控制文件共享。

1

需要独占模式的不是读取操作,而是重命名操作,因为这本质上相当于将文件移动到新位置。

我不确定,但我认为这是无法完成的。尝试复制文件,稍后在不再读取时删除/替换旧文件。


1

Win32 文件系统语义要求您在重命名文件时,该文件不应处于打开状态(以任何方式)。 您需要关闭文件,然后重命名它,并创建新的日志文件。

Unix 文件系统语义允许您重命名已打开的文件,因为文件名只是指向 inode 的指针。


1

如果你只是从文件中读取内容,那么可以使用Windows API的CreateFile来实现。只需将FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE作为dwShareMode的输入参数即可。

不幸的是,这种方法并不跨平台。但是在Linux上可能有类似的解决方案。

请参阅MSDN获取更多关于CreateFile的信息

编辑:关于Greg Hewgill的评论,我刚刚测试了一下FILE_SHARE*的方法(以确保100%正确)。如果你以只读方式打开文件并指定FILE_SHARE*参数,那么在Windows中既可以删除文件,也可以重命名文件。


0

我会确保你不要保持文件处于打开状态。例如,如果你的应用程序崩溃,这可能会导致一些奇怪的问题。 我会这样做:

  1. 将抽象(读取/写入/切换到新文件)放入一个类中,并在需要切换到新文件时关闭该文件。 (这是一种最简洁的方法,而且由于您已经有了切换代码,您已经完成了一半的工作。)
  2. 如果你必须有多个读/写访问点,需要所有fstream功能,并且不想编写完整的包装器,那么我能想到的唯一跨平台解决方案就是在不需要文件时始终关闭文件,并在需要切换文件之前多次尝试获取对文件的独占访问权限。

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