windows C++:以非独占模式打开文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27700/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ : Opening a file in non exclusive mode
提问by Steve Gury
I have to develop an application which parses a log file and sends specific data to a server. It has to run on both Linux and Windows.
我必须开发一个应用程序来解析日志文件并将特定数据发送到服务器。它必须在 Linux 和 Windows 上运行。
The problem appears when I want to test the log rolling system (which appends .1 to the name of the creates a new one with the same name). On Windows (haven't tested yet on Linux) I can't rename a file that I have opened with std::ifstream() (exclusive access?) even if I open it in "input mode" (ios::in).
当我想测试日志滚动系统(将 .1 附加到名称后会创建一个具有相同名称的新系统)时,就会出现问题。在 Windows 上(尚未在 Linux 上测试过)我无法重命名使用 std::ifstream() 打开的文件(独占访问?),即使我以“输入模式”(ios::in)打开它.
Is there a cross-platform way to open file in a non-exclusive way?
是否有跨平台的方式以非排他方式打开文件?
采纳答案by DrPizza
Is there a way to open file in a non-exclusive way,
有没有办法以非排他的方式打开文件,
Yes, using Win32, passing the various FILE_SHARE_Xxxx flags to CreateFile.
是的,使用 Win32,将各种 FILE_SHARE_Xxxx 标志传递给 CreateFile。
is it cross platform?
是跨平台的吗?
No, it requires platform-specific code.
不,它需要特定于平台的代码。
Due to annoying backwards compatibility concerns (DOS applications, being single-tasking, assume that nothing can delete a file out from under them, i.e. that they can fclose() and then fopen() without anything going amiss; Win16 preserved this assumption to make porting DOS applications easier, Win32 preserved this assumption to make porting Win16 applications easier, and it's awful), Windows defaults to opening files exclusively.
由于烦人的向后兼容性问题(DOS 应用程序是单任务,假设没有任何东西可以从它们下面删除文件,即它们可以 fclose() 然后 fopen() 没有任何问题;Win16 保留了这个假设DOS 应用程序移植更容易,Win32 保留了这个假设以使移植 Win16 应用程序更容易,这很糟糕),Windows 默认以独占方式打开文件。
The underlying OS infrastructure supports deleting/renaming open files (although I believe it does have the restriction that memory-mapped files cannot be deleted, which I think isn't a restriction found on *nix), but the default opening semantics do not.
底层操作系统基础结构支持删除/重命名打开的文件(虽然我相信它确实有不能删除内存映射文件的限制,我认为这不是 *nix 上的限制),但默认的打开语义不支持。
C++ has no notion of any of this; the C++ operating environment is much the same as the DOS operating environment--no other applications running concurrently, so no need to control file sharing.
C++ 对此没有任何概念;C++运行环境与DOS运行环境大同小异——没有其他应用程序并发运行,无需控制文件共享。
回答by Konrad Rudolph
It's not the reading operation that's requiring the exclusive mode, it's the rename, because this is essentially the same as moving the file to a new location.
需要独占模式的不是读取操作,而是重命名,因为这与将文件移动到新位置基本相同。
I'm not sure but I don't think this can be done. Try copying the file instead, and later delete/replace the old file when it is no longer read.
我不确定,但我不认为这是可以做到的。尝试复制文件,然后在不再读取旧文件时删除/替换旧文件。
回答by Greg Hewgill
Win32 filesystem semantics require that a file you rename not be open (in any mode) at the time you do the rename. You will need to close the file, rename it, and then create the new log file.
Win32 文件系统语义要求重命名的文件在重命名时不能打开(在任何模式下)。您需要关闭该文件,重命名它,然后创建新的日志文件。
Unix filesystem semantics allow you to rename a file that's open because the filename is just a pointer to the inode.
Unix 文件系统语义允许您重命名打开的文件,因为文件名只是指向 inode 的指针。
回答by Magnus Westin
If you are only reading from the file I know it can be done with windows api CreateFile. Just specify FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE as the input to dwShareMode.
如果您只是从文件中读取,我知道可以使用 windows api CreateFile 来完成。只需指定 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE 作为 dwShareMode 的输入。
Unfortunally this is not crossplatform. But there might be something similar for Linux.
不幸的是,这不是跨平台的。但是对于 Linux 可能有类似的东西。
See msdn for more info on CreateFile.
EDIT: Just a quick note about Greg Hewgill comment. I've just tested with the FILE_SHARE* stuff (too be 100% sure). And it is possible to both delete and rename files in windows if you open read only and specify the FILE_SHARE* parameters.
编辑:关于 Greg Hewgill 评论的简短说明。我刚刚测试了 FILE_SHARE* 的东西(也是 100% 确定)。如果您打开只读并指定 FILE_SHARE* 参数,则可以在 Windows 中删除和重命名文件。
回答by jilles de wit
I'd make sure you don't keep files open. This leads to weird stuff if your app crashes for example. What I'd do:
我会确保你不要打开文件。例如,如果您的应用程序崩溃,这会导致奇怪的事情。我会做什么:
- Abstract (reading / writing / rolling over to a new file) into one class, and arrange closing of the file when you want to roll over to a new one in that class. (this is the neatest way, and since you already have the roll-over code you're already halfway there.)
- If you must have multiple read/write access points, need all features of fstreams and don't want to write that complete a wrapper then the only cross platform solution I can think of is to always close the file when you don't need it, and have the roll-over code try to acquire exclusive access to the file a few times when it needs to roll-over before giving up.
- 将(读/写/滚动到一个新文件)抽象到一个类中,并在您想要滚动到该类中的一个新文件时安排关闭文件。(这是最简洁的方法,因为您已经有了翻转代码,所以您已经完成了一半。)
- 如果您必须有多个读/写访问点,需要 fstreams 的所有功能并且不想编写完整的包装器,那么我能想到的唯一跨平台解决方案是在您不需要时始终关闭文件,并让翻转代码尝试在文件需要翻转之前获得对文件的独占访问权限,然后再放弃。