【问题标题】:Why does ObjectOutputStream.writeObject() throw IOException?为什么 ObjectOutputStream.writeObject() 会抛出 IOException?
【发布时间】:2012-01-13 18:20:42
【问题描述】:

我目前正在开发一款基于特定事件(例如电池电量)自动更改手机状态的 Android 应用。我有一个 Profile 类,它有 3 个主要参数、名称、Event 和 State(Event 和 State 是另外 2 个自定义类)

在我的 ProfileEdit 类中,有各种组件,例如 EditText 和 Spinner 供用户配置 Profile。我需要在显示每个配置文件的 ListActivity 类中访问 Profile 类型的 ArrayList,以及获取当前 ArrayList 并添加新配置文件或更新一个配置文件的 ProfileEdit 类。

我必须首先这样做的想法是使用 ObjectOutputStream 将我的 ArrayList 写入手机 sd 卡,然后任何需要它的类都可以检索它。然而,到目前为止,我这样做的尝试最终只是抛出了一个 IOException。我的代码如下:

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/sdcard/profile.prof"));
oos.writeObject(profiles);
oos.flush();
oos.close();

profiles 对象是我要写入文件的 ArrayList。我无法弄清楚为什么这会引发异常。我尝试通过调用 writeObject("Hello"); 将对象更改为字符串;并且不再抛出异常,所以我只能假设它是 ArrayList 的问题。我的印象是 ArrayList 类实现了可序列化,而我的 Profile 类也实现了可序列化,尽管它没有实现相同的功能。

或者,如果有更好的方法可以让我的 ProfileList (ListActivity) 和 ProfileEdit 类访问同一个 ArrayList,请告诉我。

编辑:这是 IO 异常堆栈跟踪:(ProfileEdit 类的第 114 行是 writeObject() 行)

EZSettings(14788): IO Exception
EZSettings(14788): java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1535)
EZSettings(14788): java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
EZSettings(14788): java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
EZSettings(14788): java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
EZSettings(14788): java.util.ArrayList.writeObject(ArrayList.java:651)
EZSettings(14788): java.lang.reflect.Method.invokeNative(Native Method)
EZSettings(14788): java.lang.reflect.Method.invoke(Method.java:507)
EZSettings(14788): java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219)
EZSettings(14788): java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
EZSettings(14788): java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
EZSettings(14788): java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
EZSettings(14788): java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
EZSettings(14788): com.ezstatechanger.ProfileEdit.saveState(ProfileEdit.java:114)
EZSettings(14788): com.ezstatechanger.ProfileEdit.access$0(ProfileEdit.java:80)
EZSettings(14788): com.ezstatechanger.ProfileEdit$1.onClick(ProfileEdit.java:72)
EZSettings(14788): android.view.View.performClick(View.java:2538)
EZSettings(14788): android.view.View$PerformClick.run(View.java:9152)
EZSettings(14788): android.os.Handler.handleCallback(Handler.java:587)
EZSettings(14788): android.os.Handler.dispatchMessage(Handler.java:92)
EZSettings(14788): android.os.Looper.loop(Looper.java:123)
EZSettings(14788): android.app.ActivityThread.main(ActivityThread.java:3691)
EZSettings(14788): java.lang.reflect.Method.invokeNative(Native Method)
EZSettings(14788): java.lang.reflect.Method.invoke(Method.java:507)
EZSettings(14788): com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
EZSettings(14788): com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
EZSettings(14788): dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

  • IOException的消息是什么?
  • 嗨 jdprofit,我在原始问题中添加了堆栈跟踪,我希望它对您比对我更有用。谢谢。

标签: android arraylist ioexception objectoutputstream


【解决方案1】:

您的所有对象及其所有字段都需要可序列化 - 否则它们无法序列化。 IO 异常的另一个来源是没有写入 SD 卡的权限。 (除了您的应用程序之外的其他人是否需要这些数据?如果不需要,它属于 provate 区域。)

序列化配置数据很方便,但可能不是个好主意 - 如果您的对象签名更改,数据将不可读。更好的解决方案是将对象编组为 JSON 并保存此文件(无耻的自我广告:https://github.com/ko5tik/jsonserializer)

【讨论】:

  • 我的 Profile 类是 Serializable 的,ArrayList 也是,Profile 类中的属性也需要 Serializable 吗?我有权写入外部存储,没有这个它会抛出 FileNotFound 异常而不是 IO。关于将对象编组为 JSON,我查看了代码,这有点道理。要编写我的 ArrayList 我会使用 writer.beginArray();然后是一个 for 循环 write.value() 所有的配置文件,然后是 writer.endArray()?
  • 所有字段都需要序列化到。除非它们是暂时的。如果您使用我的数据绑定,则编组到 JSON 数组会更容易: JSONMarshaller.marshallArray(writer, arrayOfStuffYouLikeToMarshall);查看项目中的测试用例
  • 我明白了,看起来 JSON 是要走的路,我该如何初始化 JsonWriter?
  • 你没有初始化它。这是静态方法。只需将其填充为编写器和对象/数组即可。您将需要 GSON - 有一个精简版本,只有解析器/发射器,没有数据绑定
  • 我只找到了 GSON 流包,并将其添加到外部库中。当我做 JsonWriter 作家时;然后 JSONMarshaller.writeArray(writer, profiles);它说编写器可能尚未初始化。
【解决方案2】:

尽管 Konstantin Pribluda 为我需要做的事情找到了一个更好的解决方案,但这个问题已经解决了。

原来我愚蠢地忽略了我的 Event 和 State 类没有实现 Serializable 的事实。 Serializable 类中的任何字段也必须是 Serializable,否则会引发 IO 异常。

【讨论】:

    猜你喜欢
    • 2021-03-05
    • 2012-09-21
    • 1970-01-01
    • 1970-01-01
    • 2013-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多