Thread: Deleting Record in Binary File without Temporary File

  1. #1
    Registered User
    Join Date
    Aug 2019
    Location
    inside a singularity
    Posts
    308

    Deleting Record in Binary File without Temporary File

    I'm trying to implement a program that Deletes a Record in a binary file without the use of a temporary file.

    Code:
    class Manager
    {
    
    
    private:
    
    
    	int  ID;
    	char Name[20];
    
    
    public:
    
    
    	void AddRecord      (void);
    	void DeleteRecord   (void);
    	void DisplayRecords (void);
    
    
    }M;
    
    
    void Manager::DeleteRecord (void)
    {
    	clrscr ();
    
    
    	int SearchID;
    
    
    	cout << endl << " CHOICE: Delete Record!" << endl;
    
    
    	fstream fin ("Manager.dat" , ios::in | ios::nocreate | ios::binary);
    
    
    	if (!fin) cout << endl << " Error!" << endl;
    
    
    	else
    	{
    		cout << endl << " Enter ID (to be deleted): "; cin >> SearchID;
    
    
    		bool found = false;
    
    
    		fstream fout ("Manager.dat" , ios::out | ios::ate | ios::binary);
    
    
    		if (!fout) cout << endl << " Error!" << endl;
    
    
    		fout.seekp (0 , ios::beg);
    
    
    		while (fin.read ((char*)this , sizeof(Manager)))
    		{
    			if (SearchID == ID)
    			{
    				found = true;
    
    
    				continue;
    			}
    
    
    			fout.write ((char*)this , sizeof(Manager));
    		}
    
    
    		fout.close();
    
    
    		if (!found) cout << endl << " No Records with ID: " << SearchID << " found!" << endl;
    
    
    		fin.close ();
    	}
    }
    The code I've written works perfectly fine in deleting a record except there is an obvious error.

    Initial content in my file:

    1 A
    2 B
    3 C
    4 D

    In my initial file, if I choose to delete record with ID = 4, I get:

    1 A
    2 B
    3 C
    4 D

    In my initial file, if I choose to delete record with ID = 3, I get:

    1 A
    2 B
    4 D
    4 D

    In my initial file, if I choose to delete record with ID = 2, I get:

    1 A
    3 C
    4 D
    4 D

    In my initial file, if I choose to delete record with ID = 1, I get:

    2 B
    3 C
    4 D
    4 D


    What I can observe from this is that the actual data that I want to delete is being deleted but the No. of Records is still remaining 4 (the 4th one always being "4 D" in this case).

    If I take my class size as 22 Bytes( int ID being 2 on Turbo , char Name[20] being 20 ), then my file size results in 88 Bytes. So, when I delete a record my file size should end up being 66 Bytes but I do not know how to implement that. My file remains 88 Bytes as the last record always remains.

    How can I fix this?

    Thanks!

  2. #2
    Registered User
    Join Date
    Aug 2019
    Location
    inside a singularity
    Posts
    308
    I got it to work with a temporary file but I don't know how to set EOF one record before (from the end) every time I delete a record.

    Here's my code for deleting with a temporary file:

    Code:
    void Manager::DeleteRecord (void)
    {
    	clrscr ();
    
    
    	int SearchID;
    
    
    	cout << endl << " CHOICE: Delete Record!" << endl;
    
    
    	fstream fin ("Manager.dat" , ios::in | ios::nocreate | ios::binary);
    
    
    	if (!fin) cout << endl << " Error!" << endl;
    
    
    	else
    	{
    		cout << endl << " Enter ID (to be deleted): "; cin >> SearchID;
    
    
    		bool found = false;
    
    
    		fstream fout ("Temp.dat" , ios::out | ios::ate | ios::binary);
    
    
    		if (!fout) cout << endl << " Error!" << endl;
    
    
    		fout.seekp (0 , ios::beg);
    
    
    		while (fin.read ((char*)this , sizeof(Manager)))
    		{
    			if (SearchID == ID)
    			{
    				found = true;
    
    
    				continue;
    			}
    
    
    			fout.write ((char*)this , sizeof(Manager));
    		}
    
    
    		fout.close();
    
    
    		if (!found) cout << endl << " No Records with ID: " << SearchID << " found!" << endl;
    
    
    		fin.close ();
    
    
    		remove ("Manager.dat");
    
    
    		rename ("Temp.dat" , "Manager.dat");
    	}
    }

  3. #3
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    If you just want a flat binary file, and you don't want to use a secondary file, and you don't want to read the entire file into memory, and you want to use standard C++, and you apparently do want all this with the exception of clear screen, you need to set aside one identifier that says "this record has been deleted". Your actual file would still be 88 bytes, or whatever, but you will have records that are empty. Say you use negative one after deleting record four you'd have:

    1 A
    2 B
    3 C
    -1 Empty Record

    [Edit]
    Also, your approach to this is very wrong if you are doing what I think you are doing.

    The data you are managing shouldn't be part of the manager class.
    You shouldn't be changing `this` with respect to `this` identity when you remove a record from a file being managed.
    I could go on, but I'd like to see you fix the code first.
    [/Edit]
    Last edited by phantomotap; 09-20-2019 at 05:18 PM.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  4. #4
    Registered User
    Join Date
    Aug 2019
    Location
    inside a singularity
    Posts
    308
    If you just want a flat binary file, and you don't want to use a secondary file, and you don't want to read the entire file into memory, and you want to use standard C++, and you apparently do want all this with the exception of clear screen, you need to set aside one identifier that says "this record has been deleted".
    My homework problem:

    Write a menu driven program to implement Adding and Deletion of Records in a binary file. (Note: Deletion to be performed without a temporary file). Use the following class:

    Code:
    class Manager
    {
           int   ID;
          char Name[20];
    
    };
    Also, your approach to this is very wrong if you are doing what I think you are doing.

    The data you are managing shouldn't be part of the manager class.
    You shouldn't be changing `this` with respect to `this` identity when you remove a record from a file being managed.
    I could go on, but I'd like to see you fix the code first.
    As a solution, should I be reading the details into another instance of Manager instead of "this" and accordingly be rewriting?
    I didn't understand the part where you say "The data you are managing shouldn't be part of the manager class.
    You shouldn't be changing `this` with respect to `this` identity when you remove a record from a file being managed.". Could you please explain more? At school, reading a binary file record by record is the only thing I've learnt till now. Please redirect me to sites where I can learn more ways to do so...

    Thanks for your time @phantomotap!

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    There is no standard way for you to make an existing file one record shorter.

    There are various OS specific options though.
    TRUNCATE(2) Linux Programmer's Manual TRUNCATE(2)

    NAME
    truncate, ftruncate - truncate a file to a specified length

    SYNOPSIS
    #include <unistd.h>
    #include <sys/types.h>

    int truncate(const char *path, off_t length);
    int ftruncate(int fd, off_t length);
    Binary files are often easiest to use if you have say
    - a specific record value that indicates that a record has been deleted (as phantomotap suggests).
    - a separate (and much shorter) index file containing a list of which records are valid, and which are deleted.

    Adding a record becomes easier, as it's just a matter of locating a vacant slot in your data file.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Quote Originally Posted by Zeus_ View Post
    My homework problem:

    Write a menu driven program to implement Adding and Deletion of Records in a binary file. (Note: Deletion to be performed without a temporary file). Use the following class:

    Code:
    class Manager
    {
           int   ID;
          char Name[20];
    
    };


    As a solution, should I be reading the details into another instance of Manager instead of "this" and accordingly be rewriting?
    I didn't understand the part where you say "The data you are managing shouldn't be part of the manager class.
    You shouldn't be changing `this` with respect to `this` identity when you remove a record from a file being managed.". Could you please explain more? At school, reading a binary file record by record is the only thing I've learnt till now. Please redirect me to sites where I can learn more ways to do so...

    Thanks for your time @phantomotap!
    Yes. You should probably be reading into a temporary instance of the class.

    There is no reason for the manager class to have the data members it has, but if that's what you were given, I suppose that is what you should use.

    The recommendation comes from object oriented design.

    If you have a `Manager s(1, "A");`, the identity of the class, the data members `(1, "A")`, should not change to a possibly random identity, say `(4, "D")`, just because the user of class deleted an unrelated record. It makes no sense and is unexpected.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  7. #7
    Registered User
    Join Date
    Aug 2019
    Location
    inside a singularity
    Posts
    308
    If you have a `Manager s(1, "A");`, the identity of the class, the data members `(1, "A")`, should not change to a possibly random identity, say `(4, "D")`, just because the user of class deleted an unrelated record. It makes no sense and is unexpected.
    You make a good point. I'll keep it in mind and change it in my program.

    I will now be doing the reading into a temporary instance of the class and as you suggested, use a identifier say "-1 \0" for an empty record.

    Thanks!

  8. #8
    Registered User
    Join Date
    Aug 2019
    Location
    inside a singularity
    Posts
    308
    There is no standard way for you to make an existing file one record shorter.

    There are various OS specific options though.

    TRUNCATE(2) Linux Programmer's Manual TRUNCATE(2)

    NAME
    truncate, ftruncate - truncate a file to a specified length

    SYNOPSIS
    #include <unistd.h>
    #include <sys/types.h>

    int truncate(const char *path, off_t length);
    int ftruncate(int fd, off_t length);



    Oh. The assignment I got is to be done on TurboCrap and so I wouldn't be able to use <unistd.h>. I'll read more about truncate and try another version of my code on C::B

    - a specific record value that indicates that a record has been deleted (as phantomotap suggests).
    I'll use a "-1 \0" as an identifier for a deleted record and add a condition in "Display Records" to not display any records with "-1 \0"

    - a separate (and much shorter) index file containing a list of which records are valid, and which are deleted.
    This seems interesting. I'll implement this in C::B as a side project. Thanks for the idea!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. delete record from random access binary file
    By jack jordan in forum C Programming
    Replies: 1
    Last Post: 11-06-2017, 02:08 PM
  2. Binary file - delete record issue
    By ulti-killer in forum C Programming
    Replies: 1
    Last Post: 12-03-2012, 11:29 AM
  3. Deleting Text File Record
    By 01010011 in forum C++ Programming
    Replies: 5
    Last Post: 04-21-2009, 02:46 PM
  4. Deleting / Changing a record in a text file
    By clearrtc in forum C Programming
    Replies: 9
    Last Post: 08-21-2006, 12:09 AM
  5. Deleting a Record from an input file
    By goron350 in forum C++ Programming
    Replies: 5
    Last Post: 06-15-2005, 03:40 PM

Tags for this Thread