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

时间:2020-03-05 18:43:13  来源:igfitidea点击:

我必须开发一个分析日志文件并将特定数据发送到服务器的应用程序。它必须同时在Linux和Windows上运行。

当我要测试日志滚动系统(将.1添加到的名称后,会创建一个具有相同名称的新名称)时出现问题。在Windows上(尚未在Linux上进行测试),即使我以"输入模式"(ios :: in)打开文件,也无法重命名使用std :: ifstream()打开的文件(独占访问权?)。 。

是否有跨平台的方式以非独占方式打开文件?

解决方案

回答

不是读取操作需要排他模式,而是重命名,因为这本质上与将文件移动到新位置相同。

我不确定,但我不认为这可以做到。请尝试复制文件,然后在不再读取时删除/替换旧文件。

回答

Win32文件系统语义要求重命名时,重命名的文件不能以任何方式打开(以任何方式)。我们将需要关闭文件,将其重命名,然后创建新的日志文件。

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

回答

如果我们只从文件中读取文件,我知道可以使用Windows api CreateFile完成。只需指定FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE作为dwShareMode的输入。

不幸的是,这不是跨平台的。但是对于Linux可能会有类似的东西。

有关CreateFile的更多信息,请参见msdn。

编辑:关于Greg Hewgill的简短评论。我刚刚使用FILE_SHARE *进行了测试(太确定了100%)。如果我们以只读方式打开并指定FILE_SHARE *参数,则可以在Windows中删除和重命名文件。

回答

Is there a way to open file in a non-exclusive way,

是的,使用Win32,将各种FILE_SHARE_Xxxx标志传递给CreateFile。

is it cross platform?

不,它需要特定于平台的代码。

由于令人讨厌的向后兼容性问题(DOS应用程序是单任务处理,假设没有任何东西可以从它们下面删除文件,即它们可以在没有任何异常的情况下先执行fclose()然后执行fopen(); Win16保留了此假设以使Win32保留了这一假设,以使DOS应用程序的移植更加容易,而Win32则保留了这一假设,这使Windows 16应用程序的移植更加容易,而且效果很糟。

底层的操作系统基础结构支持删除/重命名打开的文件(尽管我相信它确实存在无法删除内存映射文件的限制,我认为这并不是* nix的限制),但是默认的打开语义却没有。

C ++对此没有任何概念。 C ++操作环境与DOS操作环境非常相似-没有其他应用程序同时运行,因此无需控制文件共享。

回答

我会确保我们不保持文件打开状态。例如,如果应用程序崩溃,这会导致奇怪的事情。
我会做什么:

  • 抽象(读/写/滚动到一个新文件)到一个类中,并在我们要移到该类中的新文件时安排关闭文件。 (这是最巧妙的方法,并且由于我们已经有了转换代码,因此我们已经处于中间位置。)
  • 如果必须具有多个读/写访问点,需要fstream的所有功能并且不想编写完整的包装器,那么我能想到的唯一跨平台解决方案是在不需要文件时始终关闭文件,并在文件需要放弃之前先让翻转代码尝试获取对该文件的独占访问几次。