有没有办法保存包含节点和边的图形对象?

时间:2009-05-01 13:31:16

标签: java serialization

我尝试过使用标准的序列化类型的东西,比如:

 FileOutputStream f_out;
try {
    f_out = new FileOutputStream("MAOS.data");
     ObjectOutputStream  obj_out = new ObjectOutputStream (f_out);       
     obj_out.writeObject(s);
     obj_out.flush();
     obj_out.close();

} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} ;

但问题似乎是如果我的对象在ALL中包含任何递归,我会得到堆栈溢出。如果s是包含节点和边的图(节点知道边缘以便扩展激活,并且边缘因同样的原因知道节点)则它会堆叠溢出。如果我完全消除边缘,并且只有节点知道它们应该传播激活哪些节点,那么同样的事情发生了!我甚至可以尝试保存图形知道的节点的ArrayList,并且堆栈再次溢出!

我很沮丧!

图形并不奇怪和神秘,当然有人想在我面前保存一个。我在这里看到一些关于将它们保存为XML文件的东西......但如果我的问题是递归,即使我以不同的方式保存它,我仍然不会遇到同样的问题吗?我只是想不出如果没有连接就可以制作图表!

我只是做错了,还是这个对象序列化的功能不如我想象的那么强大?或者我是否需要放弃保存图表的想法?

-Jenny

编辑,是巨大堆栈跟踪的一部分:

Exception in thread "main" java.lang.StackOverflowError
    at java.io.ObjectStreamClass.getPrimFieldValues(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.ArrayList.writeObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.ArrayList.writeObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.ArrayList.writeObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.ArrayList.writeObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)

6 个答案:

答案 0 :(得分:2)

这种结构最好像这样保存:

collection of nodes, each node has a unique ID
collection of edges, each edge has two node IDs (or however many nodes an edge connects to)

不使用任何递归。在读取节点时,创建由其ID标记的节点字典。然后使用字典在读取边缘时修复边缘。 ID不需要是对象的运行时结构的一部分,在写入/读取流时,它们只需要在数据流中是唯一的。

答案 1 :(得分:1)

您可以使用支持将图表序列化为ML格式的文本文件的JGraphT库。 GraphMLExporter Javadoc

答案 2 :(得分:0)

Java序列化可以处理任意图形(尽管不一定非常有效)。可能问题在于writeObject的自定义实现。也许堆栈跟踪的一部分可能会有所帮助。

答案 3 :(得分:0)

您应该考虑的有用的序列化格式是JSON,其中字典(由@Skizz建议)很容易表示:

  

JSONObject是名称/值对的无序集合。它的外部形式是一个用大括号包裹的字符串,名称和值之间有冒号,值和名称之间有逗号。内部表单是一个对象,具有用于按名称访问值的get()和opt()方法,以及用于按名称添加或替换值的put()方法。值可以是以下任何类型:Boolean,JSONArray,JSONObject,Number和String,或者JSONObject.NULL对象。

答案 4 :(得分:0)

Java序列化能够处理循环引用(我假设这就是递归的意思),但是已经有一个已知的大图形问题被描述为here

不要让文章的日期让你失望,只需按照其后的评论链。

似乎你必须使用另一种序列化技术来实现这一目标。已经提到了几个,有些performance metrics给了JSON高分。

答案 5 :(得分:-1)

嗯。一种解决方案是将其变为java bean并使用XMLEncoder / XMLDecoder。这是我过去用来保存和加载类的解决方案。