Java(处理)对象序列化

3

我正在尝试用Processing制作一个有颜色的正方形3D矩阵。它能够正常工作,但是当我想把它保存到文件中并序列化DataMatrix对象时,出现了java.io.NotSerializableException异常。Square和DataMatrix都实现了Serializable接口,所以我不知道可能会导致这种情况。

FileManager:

class FileManager
{

  FileManager()
  {}

  public void saveMatrix(String path, DataMatrix dm)
  {
    try
    {
    FileOutputStream file = new FileOutputStream(path);
    ObjectOutputStream output = new ObjectOutputStream(file);
    output.writeObject(dm); 
    output.close();
    }
    catch (Exception e)
    {
       e.printStackTrace();
    }
  } 

  public DataMatrix openMatrix(String path)
  {
    DataMatrix dm = null;

    try
    {

       FileInputStream file = new FileInputStream(path);
       ObjectInputStream input = new ObjectInputStream(file);
       Object aux = input.readObject();
       input.close();
       if(aux instanceof DataMatrix)
       {
         dm = (DataMatrix)aux;
       }        
    }
    catch (EOFException e1)
    {
       System.out.println ("Fin de fichero");
    }
    catch (Exception e2)
    {
        e2.printStackTrace();
    }

    return dm; 
  }
}

数据矩阵:

class DataMatrix implements Serializable
{

  Square[][][] dataMatrix;

  DataMatrix()
  { 
      dataMatrix = new Square[5][32][32];
  }

  public void setSquare(int x, int y, int z, color c, String type)
  {

     dataMatrix[z][x][y].setSquare(c,type);   

  }

正方形:

class Square implements Serializable
{

  public int x;
  public int y;
  public int z;
  public color c;
  public String type;

  Square(int xx, int yy, int zz, color cc, String tt){
    x = xx;
    y = yy;
    z = zz;
    c = cc;
    type = tt; 
  }

  public void setSquare(color cc, String tt){

    c = cc;
    type = tt;

  }

  public void printSquare()
  {
     println(green(c) +"  "+ type); 
  }

}

错误日志:

java.io.NotSerializableException: processing.core.PApplet$InternalEventQueue
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
    at maindatamatrix$FileManager.saveMatrix(maindatamatrix.java:105)
    at maindatamatrix.setup(maindatamatrix.java:30)
    at processing.core.PApplet.handleDraw(PApplet.java:2245)
    at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
    at processing.core.PApplet.run(PApplet.java:2141)
    at java.lang.Thread.run(Thread.java:662)
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: processing.core.PApplet$InternalEventQueue
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1332)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1666)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1322)
    at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1666)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1322)
    at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1666)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1322)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
    at maindatamatrix$FileManager.openMatrix(maindatamatrix.java:123)
    at maindatamatrix.setup(maindatamatrix.java:33)
    at processing.core.PApplet.handleDraw(PApplet.java:2245)
    at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
    at processing.core.PApplet.run(PApplet.java:2141)
    at java.lang.Thread.run(Thread.java:662)
Caused by: java.io.NotSerializableException: processing.core.PApplet$InternalEventQueue
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
    at maindatamatrix$FileManager.saveMatrix(maindatamatrix.java:105)
    at maindatamatrix.setup(maindatamatrix.java:30)
    ... 4 more

我认为可能是颜色类,所以我使用了短暂修饰符来检查它。但仍然出现相同的错误。有什么想法吗?


那是什么 color - AllTooSir
这是Processing中的本地类。 - Phob1a
@Phob1a,你说的“本地类”是什么意思? - Uwe Plonus
你实际上不需要实现Serializable接口中的任何方法。http://docs.oracle.com/javase/6/docs/api/java/io/Serializable.html - KiaMorot
抱歉,我不确定“native”是否是正确的术语。我的意思是它随Processing一起提供,您无需导入任何内容。 - Phob1a
“color” 只是一个 int - Pwdr
4个回答

5
为了实现这一目标,我必须:
  • 将所有实现Serializable的类重命名为.java,因此DataMatrix变成了DataMatrix.javaSquare变成了Square.java
  • 在这些类中使用int而不是color
  • 在这些类中添加缺失的导入
以下是代码:

SerializableTest.pde:

void setup(){
  DataMatrix dm = new DataMatrix();
  FileManager f = new FileManager();
  f.saveMatrix("/Users/me/test", dm);
}

DataMatrix.java:

import java.io.Serializable;

class DataMatrix implements Serializable
{

  Square[][][] dataMatrix;

  DataMatrix()
  { 
      dataMatrix = new Square[5][32][32];
  }

  public void setSquare(int x, int y, int z, int c, String type)
  {

     dataMatrix[z][x][y].setSquare(c,type);   

  }
}

FileManager.pde:

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.EOFException;

class FileManager
{

  FileManager()
  {}

  public void saveMatrix(String path, DataMatrix dm)
  {
    try
    {
    FileOutputStream file = new FileOutputStream(path);
    ObjectOutputStream output = new ObjectOutputStream(file);
    output.writeObject(dm); 
    output.close();
    }
    catch (Exception e)
    {
       e.printStackTrace();
    }
  } 

  public DataMatrix openMatrix(String path)
  {
    DataMatrix dm = null;

    try
    {

       FileInputStream file = new FileInputStream(path);
       ObjectInputStream input = new ObjectInputStream(file);
       Object aux = input.readObject();
       input.close();
       if(aux instanceof DataMatrix)
       {
         dm = (DataMatrix)aux;
       }        
    }
    catch (EOFException e1)
    {
       System.out.println ("Fin de fichero");
    }
    catch (Exception e2)
    {
        e2.printStackTrace();
    }

    return dm; 
  }
}

Square.java:

import java.io.Serializable;
import processing.core.*;

class Square implements Serializable
{

  public int x;
  public int y;
  public int z;
  public int c;
  public String type;

  Square(int xx, int yy, int zz, int cc, String tt){
    x = xx;
    y = yy;
    z = zz;
    c = cc;
    type = tt; 
  }

  public void setSquare(int cc, String tt){

    c = cc;
    type = tt;

  }

  public void printSquare()
  {
     //System.out.println(PApplet.green(c) +"  "+ type);
    int g = (c >> 8) & 0xFF;   // Faster way of getting green(argb)
    System.out.println(g); 
  }

}

2

看起来在文件管理器类中,try块内部,你的对象的字段又有它们自己的字段,其中一些字段没有实现Serializable接口...

如果Color类实现了Serializable接口...? 如果你正在使用一些不可序列化的第三方库,请尝试使用基于xml或其他序列化形式(如json)的序列化。


没有color这个类。Processing IDE将颜色变量视为ints - Pwdr

1

嗯,我实际上测试了你的代码,但将未知颜色类更改为简单字符串。它没有抱怨地写入文件,因此,我会假设以下内容:

  1. 也许当您声明瞬态时,您仍在运行旧版本的编译版本?这取决于您如何设置编译/运行时环境。

  2. 那么颜色类可能会引起问题。您能否准确提供该类的包名称,以便我们可以查找它?

  3. 在您的导入中,您是否百分之百确定正在像这样导入?这已经发生在我身上,主要是在eclipse中,当您让Eclipse帮助您时,您会选择错误的导入。

    import java.io.Serializable;

  4. 您使用的Java版本是什么,您在哪里运行代码?它看起来像是Applet的一部分?

根据您的最后一个答案,我可以推荐以下内容:

在Square类中存储3个变量:

private int r;
private int g;
private int b;

public void setColor(int r, int g, int b) {
    this.r = r;
    this.g = g;
    this.b = b;
}

public color getColor() {
    return color(r, g, b);
}

这样做可以解决颜色序列化问题。
顺便说一下,我假设你所指的Processing是指:http://processing.org

1

Oracle本身已经淡化了Serializable接口和DataInputStream和DataOutputStream类。

这种老式的序列化方式的问题在于,如果您更改了需要保存到二进制文件中的对象字段,则您现有的文件与软件的新版本不兼容。

我建议您定义自己的文件格式并掌控自己的命运。这需要一些前期努力,但长期来看,您就不会“陷入困境”。

我宁愿使用XML文件而不是Java的老式序列化。

或者,如果您真的想要一个二进制文件,可以使用DataInputStream和DataOutputStream并读取和写入自己的字段。

但我认为XML最好,因为生成的文件是“人类可读”的,甚至是“人类可编辑”的。

当我设计文件格式(或要传输的数据格式)时,我认为最好有一个版本号来标识它是哪个文件格式的版本。您可能不需要此文件格式版本号,但拥有它只会在未来给您带来更多的灵活性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接