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 が Serializable を実装し、インポートされているにもかかわらず、PinPW はシリアライズ可能ではないと表示されます。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 つのオブジェクトを読み取ります。最初にオブジェクトを読み取ってストリームにオブジェクトが存在することを確認したとき、次にオブジェクトを読み取ってそのタイプを判別し、それを破棄します。 次に、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 ...
 }
于 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) が 1 つ読み取り、2 回読み取り、this.PWlist[this.nrOfPW] = (PinPW)objIn.readObject(); 1 回だけであるべきところを 3 回読み取ります。PS: より多くのオブジェクトを保存したいので、while 内で final キーワードなしで Greg Kopff 構文を使用します。

于 2012-06-07T21:48:04.897 に答える
0

toFile()関数内の if-else ブロックは完全に無意味であることを指摘したかっただけです。writeObject()Object 引数を取ります。シリアライズ可能である限り、オブジェクトのタイプは気にしません。

あなたのfromFile()方法には重大な欠陥がありますが、NotSerializableException. あなたが言及している例外は実際に で発生したと思いますtoFile()

原因は非常に単純です: ObjectOutputStreamのドキュメントを十分に読んで理解していません。具体的には、オブジェクトとそのすべての非一時的なフィールド、およびその先祖クラスのすべての非一時的なフィールドは、Serializable を実装する必要があります。また、引数なしの public コンストラクターも必要です。

于 2012-06-07T22:14:46.080 に答える