【问题标题】:In C how do you delete data (a structure) from a binary file IN UNIX?在 C 语言中,如何从 UNIX 中的二进制文件中删除数据(结构)?
【发布时间】:2021-02-02 14:20:25
【问题描述】:

我有这样一群人:

struct patient{
   char name[100];
   char address[100];
   int age;
}

struct patient p1;
int f;
f = open("patients.dat",O_RDWR,S_IRUSR|S_IWUSR);

我使用 f = open...write(f,&p1,sizeof(struct patient))

编写了一个二进制文件

现在有一项任务,我必须从二进制文件中删除某些人(例如我输入的那些人)在要删除的文件中。

有什么办法可以从文件中删除,我不知道,比如将 p1 的名称、地址和年龄更改为 '\0',但它不起作用,它仍然显示“幽灵”的东西.

【问题讨论】:

  • 您不能从文件中删除数据,除非它位于文件末尾。人们通常做的是用编辑过的数据编写一个新文件。

标签: c file unix binary


【解决方案1】:

您不能在 POSIX 中从文件的中间中删除(或添加)数据——只能在末尾。您可以覆盖中间的数据,但这不会改变文件的大小。

所以如果你想从中间删除一条数据记录,你需要用其他数据覆盖它(可能将所有后续数据向下移动,或者可能只是复制最后一个元素),然后更改大小以删除最后一个元素(现在是重复的)。

你用ftruncate改变一个文件的大小

【讨论】:

  • 思想"that does not change..." -> "that can not change..."
  • 所以如果我用 1 struct 较小的数字截断文件,那么最后一个结构将被删除?
【解决方案2】:

我使用f = open...write(f,&p1,sizeof(struct patient))编写了一个二进制文件。

请阅读open(2)write(2)(以及lseek(2)close(2)ftruncate(2)inode(7)credentials(7) ...)的文档。

需要检查openwrite的返回值。

与大多数其他syscalls(2) 一样。另请参阅errno(3) 并阅读Advanced Linux Programming

您可以采用一个约定(并记录它):每个patient 条目(在您的二进制文件中)其name 以0 字节开头都被清除并且可以重复使用。

您也可以考虑使用mmap(2) 来访问您的二进制文件。如果您的二进制文件不太大(2020 年小于几 GB),这将很有效。另请参阅this 答案。

其实你可以考虑使用一些数据库库,比如sqlite。或者一些索引文件库,比如gdbm

sqlitegdbm 都是用 C 语言编码的 Linux 开源软件。通过研究他们的源代码,你会学到很多东西。

【讨论】:

    猜你喜欢
    • 2014-11-26
    • 2014-06-12
    • 1970-01-01
    • 2018-04-28
    • 2011-09-20
    • 2020-06-16
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多