2012-06-07 2 views
0

Я пытаюсь написать keyholder, и я хочу написать пароли в .dat-файл с помощью ObjectOutputStream, а затем прочитать их с помощью ObjectInputStream. Это мой код для записи объектов:Невозможно прочитать сериализуемый класс из файла .dat

public void toFile() 
{  
    try 
    { 
     ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("passwords.dat"));  
     for(int i = 0; i<this.nrOfPW; i++) 
     { 
      if(this.PWlist[i] instanceof longPW) 
      { 
       oos.writeObject((longPW)this.PWlist[i]); 
      } 
      else 
      { 
       oos.writeObject((PinPW)this.PWlist[i]); 
      } 
     } 
     oos.close(); 
    } 
    catch(IOException e) 
    { 
     e.getStackTrace(); 
    } 
} 

Это похоже на работу, но когда я пытаюсь прочитать файл снова и поместить объекты в моем PWlist массиве он говорит, что PinPW не сериализации, хотя PinPW реализует Serializable и импортируется. Базовый класс PinPW (Info) также реализует Serializable и импортирует его. Это код, где я прочитал файл:

public void fromFile() 
{ 
    try 
    { 
     ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("passwords.dat")); 
     while(objIn.readObject() != null) 
     { 
      if(this.nrOfPW == this.PWlist.length) 
      { 
       expand(10); 
      } 
      if(objIn.readObject() instanceof PinPW) 
      { 
       this.PWlist[this.nrOfPW] = (PinPW)objIn.readObject(); 
       this.nrOfPW++; 
      } 
      else 
      { 
       this.PWlist[this.nrOfPW] = (longPW)objIn.readObject(); 
       this.nrOfPW++; 
      } 
     } 
     objIn.close(); 
    } 
    catch(EOFException e) 
    { 
     e.getStackTrace(); 
    } 
    catch(IOException ex) 
    { 
     ex.printStackTrace(); 
    } 
    catch(ClassNotFoundException ex) 
    { 
     ex.printStackTrace(); 
    } 
} 

Массив PWlist является массив информации, и PinPW и longPW распространяется информация.

Что мне делать, чтобы исправить эту проблему?

+0

Не могли бы вы опубликовать созданный след исключения и стека - см. Мой ответ на возможное исправление этой проблемы и исправление * определенного * на ошибку. –

+1

[Без темы] По соглашению классы Java называются с использованием UppercaseStartingCamelCase - это означает, что ваш класс 'longPW' должен быть' LongPW'. Аналогично, переменные называются с использованием lowercaseStartingCamelCase, поэтому ваша переменная 'PWList' должна называться' pwList'. –

+0

Вы можете упростить свой метод для создания файла. Вам не нужно проверять тип объекта и бросать его при вызове 'writeObject', так как здесь параметр' Object'. Вы должны хотя бы гарантировать, что все прошедшие объекты реализуют интерфейс 'java.io.Serializable', поскольку это не выполняется компилятором (он принудительно используется потоком вывода сериализации). –

ответ

1

Давайте исправим "первую ошибку, первым" ...

В этом коде:

while(objIn.readObject() != null)       // reads object, tests then *discards* it 
{ 
    ... 

    if(objIn.readObject() instanceof PinPW)     // reads object, tests then *discards* it 
    { 
    this.PWlist[this.nrOfPW] = (PinPW)objIn.readObject(); // conditionally read an object 
    this.nrOfPW++; 
    } 
    else 
    { 
    this.PWlist[this.nrOfPW] = (longPW)objIn.readObject(); // conditionally read an object 
    this.nrOfPW++; 
    } 
} 

Каждый раз вокруг итерации цикла, вы на самом деле читать объекты. В первый раз, когда вы читаете объект, чтобы проверить, был ли он в потоке, в следующий раз, когда вы его прочитаете и определите его тип, отбросьте его. Затем вы прочитали третий объект и бросили его в зависимости от того, какой тип был отброшен. объект был.

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

Вы хотите сделать это вместо того, чтобы:

try 
{ 
    while (true) 
    { 
    final Object o = objIn.readObject();   // read the object from the stream 

    ... 

    if (o instanceof PinPW) 
    { 
     this.PWlist[this.nrOfPW] = (PinPW) o;   // cast to correct type 
     this.nrOfPW++; 
    } 
    else 
    { 
     this.PWlist[this.nrOfPW] = (longPW) o;  // cast to correct type 
     this.nrOfPW++; 
    } 
    } 
} 
catch (EOFException e) 
{ 
    // end of stream reached ... 
    // ... close the file descriptor etc ... 
} 
+0

@Psyberion Нет причин для проверки нулевого значения, если только вы не пишете нули при сериализации. Правильный тест для EOS в сериализованном потоке - это «EOFException». – EJP

+0

EDIT: комментарий в EJP включен в код. –

0

У вас есть проблема здесь.

while(objIn.readObject() != null) 
    { 
     if(this.nrOfPW == this.PWlist.length) 
     { 
      expand(10); 
     } 
     if(objIn.readObject() instanceof PinPW) 
     { 
      this.PWlist[this.nrOfPW] = (PinPW)objIn.readObject(); 
      this.nrOfPW++; 
     } 
     else 
     { 
      this.PWlist[this.nrOfPW] = (longPW)objIn.readObject(); 
      this.nrOfPW++; 
     } 
    } 

Вы читаете объект много раз. Постарайтесь сохранить его, а затем работать с ним. if (objIn.readObject() instanceof PinPW) читает один, читает дважды, this.PWlist [this.nrOfPW] = (PinPW) objIn.readObject(); читается три раза, когда это должно быть только один раз. PS: используйте синтаксис Грега Копфа внутри и без ключевого слова final, потому что вы хотите сохранить в нем больше объектов.

0

Я просто хотел указать, что блок if-else в функции toFile() совершенно бессмыслен. writeObject() принимает аргумент Object. Ему все равно, какой тип объекта он есть, если он сериализуем.

В то время как ваш метод fromFile() серьезно испорчен, он не вызвал бы NotSerializableException. Я считаю, что исключение, о котором вы говорите, действительно произошло в toFile().

Причина очень проста: вы не полностью прочитали и поняли документацию ObjectOutputStream. Чтобы быть конкретным, Object и все его непереходные поля и все непереходные поля в его классах предков должны реализовать Serializable. Он также должен иметь открытый конструктор no-arg.

+0

* «У него должен быть открытый конструктор no-arg» * - это верно для класса «Externalizable», но не для класса «Serializable». –

+0

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

+0

Вы думаете об этом [http://docs.oracle.com/javase/6/docs/api/ java/io/Serializable.html): * Чтобы разрешить сериализацию подтипов классов, не связанных с сериализацией, подтип может взять на себя ответственность за сохранение и восстановление состояния общедоступных, защищенных и (если доступно) полей пакета супертипа. подтип может взять на себя эту ответственность, только если класс, который он расширяет, имеет доступный конструктор no-arg для инициализации состояния класса. "* –

Смежные вопросы