0

我尝试编写一个密钥持有者,我想使用 ObjectOutputStream 将密码写入 .dat 文件,然后使用 ObjectInputStream 读取它们。这是我编写对象的代码:

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数组是一个Info数组,PinPW和longPW扩展了Info。

我该怎么做才能解决这个问题?

4

3 回答 3

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++;
  }
}

每次循环迭代时,您实际上都会读取3 个对象。第一次读取对象以检查流中是否存在对象,下次读取对象并确定其类型时,将其丢弃。 然后您读取第三个对象并根据丢弃对象的类型对其进行转换。

此外,正如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 ...
 }
于 2012-06-07T21:38:28.563 回答
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:在一段时间内使用 Greg Kopff 语法并且不使用 final 关键字,因为您想在其中保存更多对象。

于 2012-06-07T21:48:04.897 回答
0

我只是想指出toFile()函数中的 if-else 块是完全没有意义的。writeObject()接受一个对象参数。它不关心它是什么类型的 Object,只要它是可序列化的。

虽然您的fromFile()方法存在严重缺陷,但它不会导致NotSerializableException. 我相信您所指的异常实际上发生在toFile().

原因很简单:您没有完全阅读和理解ObjectOutputStream的文档。具体来说,对象及其所有非瞬态字段及其祖先类中的所有非瞬态字段都必须实现可序列化。它还必须有一个公共的无参数构造函数。

于 2012-06-07T22:14:46.080 回答