1

I am opening a serialized file that has all of my records stored. The code finds a match between the current record's object ID number property and the number in the respective textbox. I want to delete the record if there is a match. Best way to do this?

Item readItem = new Item();
BinaryFormatter bFormatter = new BinaryFormatter();
FileStream inFile = new FileStream(@"C:\file.dat", FileMode.Open, FileAccess.Read);

while (inFile.Position < inFile.Length)
    readItem = (Item)bFormatter.Deserialize(inFile);
    if (readItem.ID.ToString() == IDTextBox.Text)
{

    ??????

 }
droog114
  • 51
  • 1
  • 2
  • 3
  • 2
    Best way to do this: Don't use a BinaryFormatter produced file as a database. BinaryFormatter is a transport format, not a storage format. Just a slight version or API different between the version that created the file and the current version trying to read the file and you won't be able to open anything. – Lasse V. Karlsen Nov 30 '11 at 19:16

2 Answers2

2

You need to deserialize the file, remove the item from the list and then reserialize the whole thing. You would be better off using a file-based database like SQLLite and just serializing the records to blobs inside a row.

Ted Elliott
  • 3,415
  • 1
  • 27
  • 30
1

It depends on whether you have fixed size records or varying size records.

Varying size records

Well, what you need to do is move up all the content of the file following the record you want to get rid of, to overwrite the part you want to remove, and then truncate the file. This is slightly hard to do in-place (ie. inside the same file), as you can only read enough data to avoid overwriting the rest of the file each iteration of your move-up-loop.

A simpler method that will create a new file from the old is as follows:

  1. Make a note of the position of the stream before you deserialize an item
  2. If the item match, make a note of the position of the stream as it is now (the two positions now delineate the area of the file where the record you want to get rid of is)
  3. Create a new file, and first copy, from the start, the same number of bytes as the first position, from the old stream (the one you found the record in), to the new stream
  4. Position the old stream at the position you noted after the record you found, and copy everything that you can find from there on out into the new stream

This will create a new file with the same content as the old, except that you skip the record you want to get rid of.

If you can loop through all the records and simply determine if you want to keep it or not, here's an even simpler method:

  1. Open up a new stream
  2. Deserialize an item from the old stream
  3. If you want to keep it, serialize it back into the new stream
  4. And so on for the rest of the items.

Fixed size records

Simply read the last record of the file, position the file back to the position of the record you want to remove, and overwrite it with the contents of the last record that you just read, then truncate the file just before the last record of the file.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • Lasse, thank you. It was quite simply a matter of making a match and then doing nothing with the current record, moving on to the next record and serializing and streaming back to the file. Simplicity is the ultimate sophistication. – droog114 Nov 30 '11 at 19:33