【问题标题】:deleting a record in binary mode without creating a temp file (C file I/O)以二进制模式删除记录而不创建临时文件(C 文件 I/O)
【发布时间】:2014-12-19 04:38:34
【问题描述】:

到目前为止我提到的所有代码都使用临时文件从文件中删除记录。
例如:

fp=fopen(“foo.db”,”rb”);
ft=fopen(“temp.db”,”wb”);
//check both files opened or created successfully. Terminate program accordingly 
while(fread(&foo,sizeof(Foo),1,fp))
{
    if(record matched)
    {
        //skip this record
    }
    else
    {
        //write a record in temp file
        fwrite(&foo,sizeof(Foo),1,ft);
    }
}

fclose(fp);
fclose(ft);
remove(“foo.db”); //remove original file
rename(“temp.db”,”foo.db”); //rename temp.db to foo.db

这是我们实现删除记录的唯一方法吗?
我可以考虑将下一条记录与上一条记录重叠。
但是如何以二进制模式终止最后一条记录并标记文件结尾?
我也看到了this post,但没有任何线索

【问题讨论】:

  • @Sagar:在哪个操作系统上?这些记录和文件包含什么?请编辑您的问题以改进它!
  • @BasileStarynkevitch 我认为代码依赖于 c 编译器,可以移植到任何操作系统上。我想我们可以通过某种方式以二进制模式标记文件的结尾。虽然我同意你的回答。甚至我也这么认为。但thanx以获得更多澄清。

标签: c file-handling


【解决方案1】:

您总是可以原地重写文件。充其量你打开文件两次,第一次在“r”模式下,第二次在“w+”模式下,你用你展示的算法扫描整个文件并在最后截断它:关闭读取描述符,截断写入描述符,关闭写入描述符。

如果操作系统不允许你打开文件两次,你可以只用一个文件描述符做同样的事情,使用ftell分别记录最后的读取和写入位置,然后 fseek 来回移动。

但我认为你应该想要这样做。临时文件不仅允许更简单的算法,而且还提供更健壮的算法。如果出现故障(控制台中断、杀死错误的 PID、断电、打雷……),原始文件保持不变,直到新文件被完全写入。很容易恢复。但是,如果您尝试在原地重写,如果程序在重写过程中中断,则唯一的文件处于未确定状态并且所有数据都可能丢失 - 或者至少需要更艰难的恢复过程.但它是你的文件,承担风险:-)

【讨论】:

    【解决方案2】:

    它可能是特定于操作系统的。一般来说,files 是一个字节序列,不能去掉中间的一段字节。您应该考虑使用提供像GDBM 这样的索引文件的库,或者像Sqlite 这样的数据库(或者像PostGreSQLMongoDbMariaDb 等真正的DBMS)

    GDBM 和 Sqlite(通常是真正的 DBMS)都构建在现有文件系统之上,但提供了一些高级抽象。

    换句话说,如果您想避免复制它们,则不应在您的情况下使用纯二进制文件。正如user3121023 所评论的那样,您可以管理固定长度记录中的链接并管理空闲列表等......像 GDBM 和 Sqlite 这样的库也可以做类似的事情。

    我知道没有文件系统或操作系统可以删除中间的一段字节,也没有POSIX API 用于此。

    【讨论】:

    • 谢谢巴西尔。总而言之,这是迄今为止唯一的解决方案。可以使用数据结构中的字段,如已删除 = 1 或已删除 = 0。这样可以跳过读取记录,并且当需要删除的记录太多时,应遵循临时文件程序。这样可以提高性能。
    • 不相关:SQLitePostgreSQL 一样多的真实数据库。 sqlite 的实例可能比 postgres 多。它们的用例可能不同。
    • @Sagar:考虑一下内存管理器在调用free(obj) 时的作用或文件系统在执行rm file 时的作用时可能会有不同的策略——查看各种碎片整理API。
    猜你喜欢
    • 1970-01-01
    • 2021-11-27
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2014-03-12
    相关资源
    最近更新 更多