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

Posted

技术标签:

【中文标题】C++:以非独占模式打开文件【英文标题】:C++ : Opening a file in non exclusive mode 【发布时间】:2008-08-26 10:24:10 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

有没有办法以非独占方式打开文件,

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

它是跨平台的吗?

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

由于令人讨厌的向后兼容性问题(DOS 应用程序是单任务的,假设没有任何东西可以从它们下面删除文件,即它们可以 fclose() 然后 fopen() 没有任何问题;Win16 保留了这一点假设使移植 DOS 应用程序更容易,Win32 保留了这个假设,使移植 Win16 应用程序更容易,这很糟糕),Windows 默认以独占方式打开文件。

底层操作系统基础架构支持删除/重命名打开的文件(虽然我相信它确实有内存映射文件不能被删除的限制,我认为这不是在 *nix 上发现的限制),但默认的打开语义不要。

C++ 对此一无所知; C++操作环境与DOS操作环境大体相同——没有其他应用程序同时运行,因此无需控制文件共享。

【讨论】:

【参考方案2】:

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

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

【讨论】:

【参考方案3】:

Win32 文件系统语义要求您重命名的文件在您重命名时不要打开(在任何模式下)。您需要关闭该文件,重命名它,然后创建新的日志文件。

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

【讨论】:

【参考方案4】:

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

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

See msdn for more info on CreateFile.

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

【讨论】:

【参考方案5】:

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

    将(读取/写入/滚动到新文件)抽象到一个类中,并在您想要滚动到该类中的新文件时安排关闭文件。 (这是最简洁的方法,因为您已经有了翻转代码,所以您已经成功了一半。) 如果您必须有多个读/写访问点,需要 fstreams 的所有功能并且不想编写完整的包装器,那么我能想到的唯一跨平台解决方案是在您不这样做时始终关闭文件不需要它,并让翻转代码在放弃之前尝试几次获得对文件的独占访问权。

【讨论】:

以上是关于C++:以非独占模式打开文件的主要内容,如果未能解决你的问题,请参考以下文章

c++文件操作的文件保护方式选择项

如何告诉 emacs 在 C++ 模式下打开 .h 文件?

在 Linux 中独占打开一个设备文件

它已经被别的用户以独占方式打开,或没有查看数据的权限。

Excel 文件 - 它已被其他用户以独占方式打开,

数据库引擎打不开文件'(未知的)'。 它已经被别的用户以独占方式打开,或没有查看数据的权限。