我尝试编写一个keyholder,我想使用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。
我该怎么做才能解决这个问题?
答案 0 :(得分: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的End of Stream的正确方法是捕获文件异常结束。
你想这样做:
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 ...
}
答案 1 :(得分: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关键字,因为你想在其中保存更多对象。
答案 2 :(得分:0)
我只是想指出toFile()
函数中的if-else块是完全没有意义的。 writeObject()
接受Object参数。它不关心它是什么类型的对象,只要它是可序列化的。
虽然您的fromFile()
方法存在严重缺陷,但不会导致NotSerializableException
。我相信您所指的例外实际上发生在toFile()
。
原因很简单:您没有完全阅读并理解ObjectOutputStream的文档。具体而言,Object及其所有非瞬态字段和其祖先类中的所有非瞬态字段都必须实现Serializable。它还必须有一个公共的无参数构造函数。