对象流的问题

xhf1234 2008-05-22 09:31:35
1、ObjectInputStream() 的readObject()用于读入对象
ObjectOutputStream() 的writeObject()用于写入对象
那么请问怎么修改文件里的对象呢?
比如说文件“student.dat” 里有个对象stu; 我怎么能修改stu.name 的值呢?
2、加入student.dat 是个空文件
FileInputStream file = new FileInputStream(student.dat);
ObjectInputStream in = new ObjectInputStream(file);
stu = in.readObject();会返回null还是怎样? 我运行了一下抛出IOException 了~
3、writeObject()是追加吗?能重写ObjectOutputStream吗?

谢谢大虾们了~~~
...全文
392 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
ThirdDimension 2008-05-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 genie2138 的回复:]
引用 1 楼 java_xinjun 的回复:
建议楼主详细查看java编程思想的java.io章节,有io详细的描述;


这是一本好书
[/Quote]

但是这本书不适合初学者,先看java核心技术吧
hmsuccess 2008-05-24
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 yirentianran 的回复:]
Java codeimportjava.io.*;importjava.util.*;classDataimplementsSerializable {//实现序列话接口privateintn;publicData(intn) {this.n=n;
}publicintgetN() {returnn;
}publicvoidsetN(intn) {this.n=n;
}publicString toString() {returnInteger.toString(n);
}
}classWormimplementsSerializable {privatestaticfinallongserialVersionUID=-935278024637286504L;publicstaticvoidmain(String[] args)throws…
[/Quote]
学习了
xhf1234 2008-05-24
  • 打赏
  • 举报
回复
。。。
大侠能给点具体的代码么?
Shine_Panda 2008-05-23
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 xhf1234 的回复:]
我重点是想知道怎么修改文件里存的对象?
ObjectInputStream() 的readObject()用于读入对象
ObjectOutputStream() 的writeObject()用于写入对象
那么请问怎么修改文件里的对象呢?
比如说文件“student.dat” 里有个对象stu; 我怎么能修改stu.name 的值呢?
[/Quote]
直接修改文件是不能实现的.
要先反序列化..修改后再重新序列化.
胡矣 2008-05-23
  • 打赏
  • 举报
回复

import java.io.*;
import java.util.*;

class Data implements Serializable { // 实现序列话接口
private int n;

public Data(int n) {
this.n = n;
}

public int getN() {
return n;
}

public void setN(int n) {
this.n = n;
}

public String toString() {
return Integer.toString(n);
}
}

class Worm implements Serializable {
private static final long serialVersionUID = -935278024637286504L;

public static void main(String[] args) throws ClassNotFoundException,
IOException { // 序列话读入和写入Object可能会有这两个异常
// 将你要序列化的object,保留到一个文件中
Random rand = new Random();
Data d = new Data(rand.nextInt(10)); // 构建你需要序列话的Object
System.out.println("d = " + d);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
"c:\\worm.out")); // 准备写入的文件
out.writeObject(d);
out.flush();
out.close(); // 执行到这里你可以看见worm.out这个文件,
// 以下的代码读出你刚刚写入Object
ObjectInputStream in = new ObjectInputStream(new FileInputStream(
"c:\\worm.out")); // 读你刚刚写入的文件
Data d2 = (Data) in.readObject(); // 重新构建你刚刚写入的Object
System.out.println("d2 = " + d2);
d2.setN(99);
//然后在写入对象,不就完成修改了吗....

}
}

xhf1234 2008-05-23
  • 打赏
  • 举报
回复
我重点是想知道怎么修改文件里存的对象?
ObjectInputStream() 的readObject()用于读入对象
ObjectOutputStream() 的writeObject()用于写入对象
那么请问怎么修改文件里的对象呢?
比如说文件“student.dat” 里有个对象stu; 我怎么能修改stu.name 的值呢?
genie2138 2008-05-22
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 java_xinjun 的回复:]
建议楼主详细查看java编程思想的java.io章节,有io详细的描述;
[/Quote]

这是一本好书
jdlsfl 2008-05-22
  • 打赏
  • 举报
回复
搂主看一下jdk应该就比较清楚了
上面摘自jdk,问题就不回答了
jdlsfl 2008-05-22
  • 打赏
  • 举报
回复
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。

writeObject 方法用于将对象写入流中。所有对象(包括 String 和数组)都可以通过 writeObject 写入。可将多个对象或基元写入流中。必须使用与写入对象时相同的类型和顺序从相应 ObjectInputstream 中读回对象。

还可以使用 DataOutput 中的适当方法将基本数据类型写入流中。还可以使用 writeUTF 方法写入字符串。

对象的默认序列化机制写入的内容是:对象的类,类签名,以及非瞬态和非静态字段的值。其他对象的引用(瞬态和静态字段除外)也会导致写入那些对象。可使用引用共享机制对单个对象的多个引用进行编码,这样即可将对象的图形恢复为最初写入它们时的形状。

例如,要写入可通过 ObjectInputStream 中的示例读取的对象,请执行以下操作:


FileOutputStream fos = new FileOutputStream("t.tmp");
ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeInt(12345);
oos.writeObject("Today");
oos.writeObject(new Date());

oos.close();
在序列化和反序列化过程中需要特殊处理的类必须实现具有下列准确签名的特殊方法:


private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException;
private void writeObject(java.io.ObjectOutputStream stream)
throws IOException
private void readObjectNoData()
throws ObjectStreamException;
writeObject 方法负责写入特定类的对象状态,以便相应的 readObject 方法可以恢复它。该方法本身不必与属于对象的超类或子类的状态有关。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。

序列化操作不写出没有实现 java.io.Serializable 接口的任何对象的字段。不可序列化的 Object 的子类可以是可序列化的。在此情况下,不可序列化的类必须有一个无参数构造方法,以便允许初始化其字段。在此情况下,子类负责保存和恢复不可序列化的类的状态。经常出现的情况是,该类的字段是可访问的(public、package 或 protected),或者存在可用来恢复状态的 get 和 set 方法。

在 writeObject 和 readObject 方法的实现中抛出 NotSerializableException,可以阻止对象的序列化。ObjectOutputStream 将捕获异常并中止序列化进程。

实现 Externalizable 接口允许对象假定可以完全控制对象的序列化形式的内容和格式。调用 Externalizable 接口的方法(writeExternal 和 readExternal)来保存和恢复对象的状态。通过类实现时,它们可以使用 ObjectOutput 和 ObjectInput 的所有方法读写它们自己的状态。对象负责处理出现的任何版本控制。

Enum 常量的序列化不同于普通的 serializable 或 externalizable 对象。enum 常量的序列化形式只包含其名称;常量的字段值不被传送。为了序列化 enum 常量,ObjectOutputStream 需要写入由常量的名称方法返回的字符串。与其他 serializable 或 externalizable 对象一样,enum 常量可以作为序列化流中后续出现的 back 引用的目标。用于序列化 enum 常量的进程不可定制;在序列化期间,由 enum 类型定义的所有类特定的 writeObject 和 writeReplace 方法都将被忽略。类似地,任何 serialPersistentFields 或 serialVersionUID 字段声明也将被忽略,所有 enum 类型都有一个 0L 的固定的 serialVersionUID。

基本数据(不包括 serializable 字段和 externalizable 数据)以块数据记录的形式写入 ObjectOutputStream 中。块数据记录由头部和数据组成。块数据部分包括标记和跟在部分后面的字节数。连续的基本写入数据被合并在一个块数据记录中。块数据记录的分块因子为 1024 字节。每个块数据记录都将填满 1024 字节,或者在终止块数据模式时被写入。调用 ObjectOutputStream 方法 writeObject、defaultWriteObject 和 writeFields 最初只是终止所有现有块数据记录。

jdlsfl 2008-05-22
  • 打赏
  • 举报
回复
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。

ObjectInputStream 确保从流创建的图形中所有对象的类型与 Java 虚拟机中显示的类相匹配。使用标准机制按需加载类。

只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流读取。

readObject 方法用于从流读取对象。应该使用 Java 的安全强制转换来获取所需的类型。在 Java 中,字符串和数组都是对象,所以在序列化期间将其视为对象。读取时,需要将其强制转换为期望的类型。

可以使用 DataInput 上的适当方法从流读取基本数据类型。

默认情况下,对象的反序列化机制会将每个字段的内容恢复为写入时它所具有的值和类型。反序列化进程将忽略声明为瞬态或静态的字段。对其他对象的引用使得根据需要从流中读取这些对象。使用引用共享机制能够正确地恢复对象的图形。反序列化时始终分配新对象,这样可以避免现有对象被重写。

读取对象类似于运行新对象的构造方法。为对象分配内存并将其初始化为零 (NULL)。为不可序列化类调用无参数构造方法,然后从以最接近 java.lang.object 的可序列化类开始和以对象的最特定类结束的流恢复可序列化类的字段。

例如,要从由 ObjectOutputStream 中的示例写入的流读取:


FileInputStream fis = new FileInputStream("t.tmp");
ObjectInputStream ois = new ObjectInputStream(fis);

int i = ois.readInt();
String today = (String) ois.readObject();
Date date = (Date) ois.readObject();

ois.close();
类控制实现 java.io.Serializable 或 java.io.Externalizable 接口时的序列化方式。

实现 Serializable 接口允许对象序列化,以保存和恢复对象的全部状态,并且允许类在写入流时的状态和从流读取时的状态之间变化。它自动遍历对象之间的引用,保存和恢复全部图形。

在序列化和反序列化进程中需要特殊处理的 Serializable 类应该实现以下方法:


private void writeObject(java.io.ObjectOutputStream stream)
throws IOException;
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
readObject 方法负责使用通过对应的 writeObject 方法写入流的数据,为特定类读取和恢复对象的状态。该方法本身的状态,不管是属于其超类还是属于其子类,都没有关系。恢复状态的方法是,从个别字段的 ObjectInputStream 读取数据并将其分配给对象的适当字段。DataInput 支持读取基本数据类型。

尝试读取由对应的 writeObject 方法写入的超出自定义数据边界的对象数据将导致抛出 OptionalDataException(eof 字段值为 true)。超出已分配数据末尾的非对象读取以指示流末尾的方式反映数据结束:按位读取与字节读取或字节数读取一样,将返回 -1,基元读取将抛出 EOFException。如果不存在对应的 writeObject 方法,则默认的序列化数据的末尾标记已分配数据的末尾。

从 readExternal 方法发出的基元和对象读取调用的行为方式一样:如果流已经定位在由相应 writeExternal 方法写入的数据末尾,则对象读取将抛出 OptionalDataException(其 eof 设置为 true),按位读取将返回 -1,基元读取将抛出 EOFException。注意,此行为不适用于使用旧 ObjectStreamConstants.PROTOCOL_VERSION_1 协议写入的流,在这些流中,没有划分出由 writeExternal 方法写入的数据末尾,因此无法检测。

如果序列化流没有将给定类列为要反序列化的对象的超类,则 readObjectNoData 方法负责初始化其特定类的对象状态。在接收方使用的反序列化实例类的版本不同于发送方,并且接收者版本扩展的类不是发送者版本扩展的类时,此事可能发生。如果序列化流已经被篡改,也会发生这种情况;因此,不管源流是“敌意的”还是不完整的,readObjectNoData 方法都可以用来正确地初始化反序列化的对象。

对于没有实现 java.io.Serializable 接口的任何对象,序列化不会对其字段进行读取或赋值。非 serializable 的 Object 的子类可以为 serializable。在此情况下,非 serializable 类必须具有无参数的构造方法以允许其字段能被初始化。在此情况下,子类负责保存和恢复非 serializable 类的状态。经常出现的情况是,该类的字段是可访问的(public、package 或 protected),或者存在可用于恢复状态的 get 和 set 方法。

反序列化对象进程中发生的所有异常将由 ObjectInputStream 捕获并将中止读取进程。

实现 Externalizable 接口允许对象假定可以完全控制对象的序列化形式的内容和格式。调用 Externalizable 接口的方法(writeExternal 和 readExternal)来保存和恢复对象状态。当这两种方法被某个类实现时,它们可以使用 ObjectOutput 和 ObjectInput 的所有方法读写其本身的状态。对象负责处理出现的任何版本控制。

Enum 常量的反序列化不同于普通的 serializable 或 externalizable 对象。Enum 常量的序列化形式只包含其名称;不传送常量的字段值。要反序列化 enum 常量,ObjectInputStream 需要从流中读取常量的名称;然后将 enum 常量的基本类型和接收到的常量名称作为参数,调用静态方法 Enum.valueOf(Class, String) 获取反序列化的常量。与其他 serializable 或 externalizable 对象一样,enum 常量可以作为序列化流中随后出现的反向引用的目标。不可以自定义 enum 常量的反序列化进程:在反序列化期间,enum 类型所定义的任何与类有关的 readObject、readObjectNoData 和 readResolve 方法都将被忽略。类似地,任何 serialPersistentFields 或 serialVersionUID 字段声明也将被忽略(所有 enum 类型都有一个固定的 0L 的 serialVersionUID)。
lifanfly 2008-05-22
  • 打赏
  • 举报
回复
建议楼主详细查看java编程思想的java.io章节,有io详细的描述;

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧