3

All the codes so far I referred uses temp file to delete a record from file.
Ex:

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

is this the only way we can implement deleting record ?
i can think of overlaping next record to previous record.
but how do i terminate last record and mark end of file in binary mode ?
i also saw this post but no clues

Community
  • 1
  • 1
Sagar
  • 228
  • 1
  • 17
  • @Sagar: On which operating system? And what do these records and files contain? Please edit your question to improve it! – Basile Starynkevitch Oct 23 '14 at 13:48
  • @BasileStarynkevitch i think code is c compiler dependent and can be ported on any os. i thought there are someways we can mark the end of file in binary mode. although i agree with you answer. even i thought the same. but thanx for more clarification. – Sagar Oct 24 '14 at 11:10

2 Answers2

2

It could be operating system specific. In general, files are a sequence of bytes, and you cannot remove a segment of bytes in the middle. You should consider using a library providing indexed files like GDBM, or a database like Sqlite (or a real DBMS like PostGreSQL, MongoDb, MariaDb etc....)

Both GDBM and Sqlite (and often real DBMS) are built above existing file systems, but provide some high-level abstraction.

In other words, you should not use plain binary files in your case, if you want to avoid copying them. As commented by user3121023 you might manage links in your fixed length records and manage a free list, etc... Libraries like GDBM and Sqlite are also able to do something similar.

I know no file system or operating system which is able to remove a segment of bytes in the middle, and there is no POSIX API for this.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Thank you Basile. To sum up, this is the only solution so far. one can use field in data structure like deleted=1 or deleted=0. so that record can be skipped from reading and when there are so many records that needs to be deleted one should follow the temp file procedure. this way performance can be increased. – Sagar Oct 24 '14 at 11:07
  • unrelated: `SQLite` is as much real db as `PostgreSQL`. There are probably more instances of sqlite than postgres. Their use-cases may differ. – jfs Oct 25 '14 at 07:28
  • @Sagar: there could be different strategies consider what a memory manager does when `free(obj)` is called or what a filesystem does when `rm file` is executed -- look at various defragmentation APIs. – jfs Oct 25 '14 at 07:38
1

You can always rewrite a file in place. At best you open twice the file, first in "r" mode, second in "w+" mode, you scan the whole file with the algorithm you showed and truncate it at the end : close read descriptor, truncate on write descriptor, close write descriptor.

If the OS does not allow you to open the file twice, you can do same thing with only one file descriptor using ftell to note last read and write position respectively and fseek to go back and forth.

But I think you should not want to do that. The temporary file not only allows a simpler algorythm, but also a much more robust one. In case of a failure (break on console, kill of a wrong PID, power outage, thunder, ...) the original file remains untouched until the new one is completely written. It is easy to recover. But if you try to rewrite in place, if the program breaks in the middle of rewriting the only file is in un undetermined state and all data may be lost - or at least will require a much harder recovery process. But it is your file and you take the risk :-)

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252