Удалить запись из сериализованного файла?

Я открываю сериализованный файл, в котором хранятся все мои записи. Код находит совпадение между свойством номера идентификатора объекта текущей записи и числом в соответствующем текстовом поле. Я хочу удалить запись, если есть совпадение. Лучший способ сделать это?

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)
{

    ??????

 }

person droog114    schedule 30.11.2011    source источник
comment
Лучший способ сделать это: не использовать файл, созданный BinaryFormatter, в качестве базы данных. BinaryFormatter - это транспортный формат, а не формат хранения. Просто небольшая версия или API отличается между версией, создавшей файл, и текущей версией, пытающейся прочитать файл, и вы не сможете ничего открыть.   -  person Lasse V. Karlsen    schedule 30.11.2011


Ответы (2)


Вам нужно десериализовать файл, удалить элемент из списка, а затем повторно сериализовать все это. Было бы лучше использовать базу данных на основе файлов, такую ​​как SQLLite, и просто сериализовать записи в капли внутри строки.

person Ted Elliott    schedule 30.11.2011

Это зависит от того, есть ли у вас записи фиксированного или переменного размера.

Записи разного размера

Что ж, что вам нужно сделать, так это переместить все содержимое файла после записи, от которой вы хотите избавиться, перезаписать часть, которую вы хотите удалить, а затем обрезать файл. Это немного сложно сделать на месте (то есть внутри того же файла), так как вы можете читать только достаточно данных, чтобы избежать перезаписи остальной части файла на каждой итерации вашего цикла перемещения вверх.

Более простой метод, который создаст новый файл из старого, выглядит следующим образом:

  1. Обратите внимание на положение потока перед десериализацией элемента.
  2. Если элемент совпадает, запишите положение потока, как оно есть сейчас (две позиции теперь очерчивают область файла, в которой находится запись, от которой вы хотите избавиться)
  3. Создайте новый файл и сначала скопируйте с самого начала то же количество байтов, что и в первой позиции, из старого потока (того, в котором вы нашли запись) в новый поток.
  4. Поместите старый поток в положение, которое вы отметили после найденной записи, и скопируйте все, что вы можете найти оттуда, в новый поток.

Это создаст новый файл с тем же содержимым, что и старый, за исключением того, что вы пропустите запись, от которой хотите избавиться.

Если вы можете перебрать все записи и просто определить, хотите ли вы их сохранить или нет, вот еще более простой метод:

  1. Откройте новый поток
  2. Десериализовать элемент из старого потока
  3. Если вы хотите сохранить его, сериализуйте его обратно в новый поток
  4. И так по остальным пунктам.

Записи фиксированного размера

Просто прочтите последнюю запись файла, поместите файл обратно в позицию записи, которую вы хотите удалить, и перезапишите его содержимым последней записи, которую вы только что прочитали, а затем обрежьте файл непосредственно перед последней записью файл.

person Lasse V. Karlsen    schedule 30.11.2011
comment
Лассе, спасибо. Это был просто вопрос сопоставления, а затем ничего не делать с текущей записью, переходя к следующей записи, сериализации и потоковой передачи обратно в файл. Простота есть основа утонченности. - person droog114; 30.11.2011