Проблема десериализации arraylist объектов из файла [дубликат]

A NullReferenceException бросается, когда мы пытаемся получить доступ к свойствам нулевого объекта или когда значение строки становится пустым, и мы пытаемся получить доступ к строковым методам.

Например:

  1. При использовании метода string пустой строки:
    string str = string.Empty;
    str.ToLower(); // throw null reference exception
    
  2. Когда свойство нулевого объекта доступно:
    Public Class Person {
        public string Name { get; set; }
    }
    Person objPerson;
    objPerson.Name  /// throw Null refernce Exception 
    
50
задан Jonas 15 October 2011 в 17:54
поделиться

5 ответов

Вот трюк: подкласс ObjectOutputStream и переопределить метод writeStreamHeader:

public class AppendingObjectOutputStream extends ObjectOutputStream {

  public AppendingObjectOutputStream(OutputStream out) throws IOException {
    super(out);
  }

  @Override
  protected void writeStreamHeader() throws IOException {
    // do not write a header, but reset:
    // this line added after another question
    // showed a problem with the original
    reset();
  }

}

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

Изменить

Я был недоволен первым наименованием класса. Это лучше: он описывает «что это такое», а не «как это сделано»

Edit

Изменено имя еще раз, чтобы уточнить, что этот поток предназначен только для добавление к существующему файлу. Он не может быть использован для создания файла new с данными объекта.

Редактировать

Добавлен вызов reset() после этого вопроса показал, что исходная версия, которая просто переопределила writeStreamHeader как no-op, в некоторых случаях могла создать поток, который не мог быть прочитан.

70
ответ дан Community 26 August 2018 в 08:53
поделиться

Как говорит API , конструктор ObjectOutputStream записывает заголовок потока сериализации в базовый поток. И этот заголовок ожидается только один раз, в начале файла. Поэтому несколько раз нажимать

new ObjectOutputStream(fos);

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

13
ответ дан abyx 26 August 2018 в 08:53
поделиться

Самый простой способ избежать этой проблемы - сохранить OutputStream открытым при записи данных, а не закрывать его после каждого объекта. Вызов reset() может быть целесообразным, чтобы избежать утечки памяти.

Альтернативой может быть чтение файла как серии последовательных ObjectInputStreams. Но это требует от вас подсчитывать, сколько байтов вы читаете (это может быть реализовано с помощью FilterInputStream), затем закрыть InputStream, снова открыть его, пропустить это много байтов и только затем обернуть его в ObjectInputStream ().

5
ответ дан Michael Borgwardt 26 August 2018 в 08:53
поделиться

Из-за точного формата сериализованного файла добавление действительно испортит его. Вы должны записать все объекты в файл как часть одного и того же потока, иначе он будет сбой при чтении метаданных потока, когда он ожидает объект.

Вы можете прочитать спецификацию Serialization Specification для более подробной информации или (проще) прочитать эту нить , где Roedy Green говорит в основном то, что я только что сказал.

7
ответ дан Michael Myers 26 August 2018 в 08:53
поделиться

Как насчет каждого раза, когда вы добавляете объект, читаете и копируете все текущие данные в файле, а затем переписываете все вместе в файл.

0
ответ дан user4147874 26 August 2018 в 08:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: