我想加入使用相同的文件名输入和输出文件到我的程序,以便它将替换输入文件的可能性。
由于处理的文件可能非常大,我认为最好的解决办法是先打开该文件,然后将其删除,并创建一个新的,也就是这样的:
/* input == output in this case */
FILE *inf = fopen(input, "r");
remove(output);
FILE *outf = fopen(output, "w");
(当然,错误处理后加)
我知道,并不是所有的系统都将让我删除打开的文件,并且只要这是可以接受的, remove()
会在这种情况下失败。
我很担心,虽然如果没有任何系统,这将让我删除打开的文件,然后无法读取其内容。
C99标准规定在这种情况下为“实现定义的行为; SUS甚至没有提及的情况。
什么是你的意见/经验? 我一定要担心呢? 我应该避免这样的解决方案?
编辑:请注意,这是不应该出现的情况下,用户的一些主线的特征,而是“不得已”指定相同的文件名作为输入和输出文件。
编辑:好的,一个问题接着:是有可能,在这种特殊情况下,我提出的解决方案是能够做更多的恶不仅仅是打开输出文件只写(即像上面,但没有remove()
调用)。
不,这不是安全的 。 它可以在文件系统上工作,但不能在其他人。 或者,它可能会间歇性。 这真的取决于你的操作系统和文件系统上。 对于在深入了解Solaris中,看到这个文章的文件旋转 。
看看GNU SED的“--in就地”选项 。 此选项可通过输出写入到一个临时文件,然后复制了原来的。 这是唯一安全的,兼容的方法。
你也应该考虑你的程序可以在任何时候失败了,由于停电或过程中被杀死。 如果发生这种情况,那么你的原始文件会丢失。 另外,对于确实具有引用计数的文件系统,你不保存任何空间,在临时文件解决方案,因为这两个文件有,直到输入关闭文件在磁盘上存在。
如果文件是巨大的,空间是非常宝贵的,开发时间很便宜,你可以打开一个单独的读/写,并确保您写指针不前进超出你读指针。
我所知道的所有的系统让你删除打开的文件,实现了某种形式的引用计数为文件中的节点。 所以,删除文件删除该目录项,但文件节点本身仍具有从打开的文件句柄一个参考。 在这样的实现,显然删除文件会不会影响到继续阅读它的能力,我很难想象实现这一行为的任何其他合理的方式。
我一直有这个在Linux / Unix系统。 永远不要在Windows,OS / 2,或(战栗)DOS。 任何其他平台上你担心?
这种行为实际上是在使用临时的磁盘空间非常有用 - 打开进行读/写文件,并立即将其删除。 它得到的程序退出(以任何理由,包括电源,停电)自动清理,并使其更难(但不是不可能的),为他人监视它(的/ proc能提供线索,如果您已经阅读访问该进程) 。