代码之家  ›  专栏  ›  技术社区  ›  Michał Górny

删除()打开的文件是否安全?

  •  4
  • Michał Górny  · 技术社区  · 15 年前

    我考虑在程序中添加对输入和输出文件使用相同文件名的可能性,这样它将替换输入文件。

    由于处理的文件可能非常大,我认为最好的解决方案是先打开文件,然后删除它并创建一个新的文件,即:

    /* input == output in this case */
    FILE *inf = fopen(input, "r");
    remove(output);
    FILE *outf = fopen(output, "w");
    

    (当然,添加了错误处理)

    我知道并非所有系统都允许我删除打开的文件,只要 remove() 在那种情况下会失败的。

    不过,我担心的是,如果没有任何系统允许我删除打开的文件,然后无法读取其内容。

    在这种情况下,C99标准将行为指定为__implementation defined_;SUS甚至没有提到这种情况。

    你的意见/经验是什么?我要担心吗?我应该避免这样的解决方案吗?

    编辑:请注意,这不应该是一些主线功能,而应该是__last resort_,在这种情况下,用户指定与输入和输出文件相同的文件名。

    编辑:好的,还有一个问题:在这种特殊情况下,我提出的解决方案是否可能比只打开输出文件写(如上面所述,但没有 移除() 打电话)

    3 回复  |  直到 15 年前
        1
  •  4
  •   brianegge    15 年前

    不,不是 安全的 .它可能在您的文件系统上工作,但在其他系统上失败。或者可能会间歇性失败。它实际上取决于您的操作系统和文件系统。要深入了解Solaris,请参见 article on file rotation .

    看一看 GNU sed's '--in-place' option . 此选项的工作方式是将输出写入临时文件,然后在原始文件上进行复制。这是唯一安全、兼容的方法。

    您还应该考虑到您的程序在任何时候都可能由于断电或进程被终止而失败。如果发生这种情况,则原始文件将丢失。此外,对于具有引用计数的文件系统,在临时文件解决方案中不节省任何空间,因为在关闭输入文件之前,两个文件都必须存在于磁盘上。

    如果文件很大,空间也很宝贵,开发人员的时间也很便宜,那么您可以打开一个用于读/写的文件,并确保您的写指针不会超出您的读指针。

        2
  •  4
  •   Pavel Minaev    15 年前

    我知道的所有允许您删除打开的文件的系统都为文件节点实现某种形式的引用计数。因此,删除文件会删除目录条目,但文件节点本身仍然有一个来自打开文件句柄的引用。在这种实现中,删除一个文件显然不会影响继续读取它的能力,我发现很难想象任何其他合理的方法来实现这种行为。

        3
  •  1
  •   Tanktalus    15 年前

    我一直都在Linux/Unix上使用它。千万不要在Windows、OS/2或(颤栗)DOS上。你还关心其他平台吗?

    这种行为实际上在使用临时磁盘空间时很有用——打开文件进行读/写,然后立即将其删除。它会在程序退出时自动清除(出于任何原因,包括断电),并使其他人更难(但并非不可能)监视它(/proc可以提供线索,如果您具有对该进程的读取权限)。