它“安全”吗?删除()打开文件?
我考虑在我的程序中添加对输入和输出文件使用相同文件名的可能性,以便它将替换输入文件。
由于处理后的文件可能很大,我认为最好的解决方案是首先打开文件,然后删除它并创建一个新文件,即像这样:(
/* input == output in this case */
FILE *inf = fopen(input, "r");
remove(output);
FILE *outf = fopen(output, "w");
当然,添加了错误处理)
我知道并非所有系统将允许我删除打开的文件,只要 remove()
在这种情况下会失败,这是可以接受的。
但我担心是否没有任何系统允许我删除该打开的文件,然后无法读取其内容。
C99 标准将这种情况下的行为指定为“实现定义的”; SUS甚至没有提到这个案子。
您的意见/经验是什么?我需要担心吗?我应该避免这样的解决方案吗?
编辑:请注意,这不应该是某些主线功能,而是用户指定相同文件名作为输入和输出文件的情况下的“最后手段”。
编辑:好的,还有一个问题:在这种特殊情况下,我提出的解决方案是否可能比仅打开只写输出文件(即像上面一样但没有 remove()
调用)更邪恶。
I think about adding possibility of using same the filename for both input and output file to my program, so that it will replace the input file.
As the processed file may be quite large, I think that best solution would to be first open the file, then remove it and create a new one, i.e. like that:
/* input == output in this case */
FILE *inf = fopen(input, "r");
remove(output);
FILE *outf = fopen(output, "w");
(of course, with error handling added)
I am aware that not all systems are going to allow me to remove open file and that's acceptable as long as remove()
is going to fail in that case.
I am worried though if there isn't any system which will allow me to remove that open file and then fail to read its' contents.
C99 standard specifies behavior in that case as ‘implementation-defined’; SUS doesn't even mention the case.
What is your opinion/experience? Do I have to worry? Should I avoid such solutions?
EDIT: Please note this isn't supposed to be some mainline feature but rather ‘last resort’ in the case user specifies same filename as both input and output file.
EDIT: Ok, one more question then: is it possible that in this particular case the solution proposed by me is able to do more evil than just opening the output file write-only (i.e. like above but without the remove()
call).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不,这不安全。它可能在您的文件系统上工作,但在其他文件系统上失败。或者它可能会间歇性失败。这实际上取决于您的操作系统和文件系统。要深入了解 Solaris,请参阅这篇有关文件轮换的文章。
看看 GNU sed 的 '--in -place'选项。此选项的工作原理是将输出写入临时文件,然后复制原始文件。这是唯一安全、兼容的方法。
您还应该考虑到您的程序可能随时因断电或进程被终止而失败。如果发生这种情况,您的原始文件将丢失。此外,对于具有引用计数的文件系统,您不会通过临时文件解决方案节省任何空间,因为这两个文件都必须存在于磁盘上,直到输入文件关闭。
如果文件很大,空间很宝贵,并且开发人员时间很便宜,您可以打开一个文件进行读/写,并确保写指针不会超出读指针。
No, it's not safe. It may work on your file system, but fail on others. Or it may intermittently fail. It really depends on your operating system AND file system. For an in depth look at Solaris, see this article on file rotation.
Take a look at GNU sed's '--in-place' option. This option works by writing the output to a temporary file, and then copying over the original. This is the only safe, compatible method.
You should also consider that your program could fail at any time, due to a power outage or the process being killed. If this occurs, then your original file will be lost. Additionally, for file systems which do have reference counting, your not saving any space, over the temp file solution, as both files have to exist on disk until the input file is closed.
If the files are huge, and space is at premium, and developer time is cheap, you may be able to open a single for read/write, and ensure that your write pointer does not advance beyond your read pointer.
据我所知,所有允许您删除打开文件的系统都为文件节点实现某种形式的引用计数。因此,删除文件会删除目录条目,但文件节点本身仍然具有来自打开文件句柄的一个引用。在这样的实现中,删除文件显然不会影响继续读取它的能力,而且我发现很难想象任何其他合理的方法来实现这种行为。
All systems that I'm aware of that let you remove open files implement some form of reference-counting for file nodes. So, removing a file removes the directory entry, but the file node itself still has one reference from open file handle. In such an implementation, removing a file obviously won't affect the ability to keep reading it, and I find it hard to imagine any other reasonable way to implement this behavior.
我一直让它在 Linux/Unix 上工作。永远不要在 Windows、OS/2 或(颤抖的)DOS 上。您还关心其他平台吗?
这种行为实际上在使用临时磁盘空间时很有用 - 打开文件进行读/写,然后立即删除它。它会在程序退出时自动清除(出于任何原因,包括断电),并使其他人更难(但并非不可能)监视它(如果您对该进程具有读取访问权限,/proc 可以提供线索) 。
I've always got this to work on Linux/Unix. Never on Windows, OS/2, or (shudder) DOS. Any other platforms you are concerned about?
This behaviour actually is useful in using temporary diskspace - open the file for read/write, and immediately delete it. It gets cleaned up automatically on program exit (for any reason, including power-outage), and makes it much harder (but not impossible) for others to monitor it (/proc can give clues, if you have read access to that process).