IO
数据流
数据流将“基本数据类型和字符串数据类型”作为数据源,从而允许程序以机器无关的方式从底层输入输出流中操作Java基本数据类型和字符串数据类型。
DateInputStream和DataOutputStream提供了可以存取与机器无关的所有Java基础类型数据(如:int、double、String等)方法。
1.DataOutputStream
使用DataOutputStream可以向文件中输出各种数据类型的数据了:
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
public class DataOutputStreamDome {
public static void main(String[] args) {
DataOutputStream dor=null;
try{
dor=new DataOutputStream(new BufferedOutputStream(new FileOutputStream("e:/111.txt")));
//向文件写入不同类型的数据
dor.write(10);
dor.writeChar('a');
dor.writeBoolean(true);
dor.writeDouble(Math.random());
dor.writeUTF("你好世界"); //写入字符串
dor.flush();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(dor!=null)
dor.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
这样虽然向文件中写入了不同类型的数据,但是所使用的是FileOutputStream,所以他还是基于字节流来输出的,所以文件中的数据是乱码。
2.DataInputStream
相对DataOutputStream,DataInputStream是从文件中读取使用DataOutputStream输出的各种类型的数据:
import java.io.*;
public class DataInputStreamDome {
public static void main(String[] args) {
DataInputStream dis=null;
try{
dis=new DataInputStream(new BufferedInputStream(new FileInputStream("e:/111.txt")));
//注意读取数据的顺序要与写入的顺序一致,否则不能正确读取数据
System.out.println(dis.readInt());
System.out.println(dis.readChar());
System.out.println(dis.readBoolean());
System.out.println(dis.readDouble());
System.out.println(dis.readUTF());
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if (dis!=null) {
dis.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
这样就能将上面写入文件中的不同类型的数据读出来了。
对象流
这里所指的对象是用来存储数据的对象,也称之为数据模型对象,对象的本质是用来组织和存储数据的,对象本身也是数据。通过序列化和反序列化我们可以将对象存储到硬盘上的文件中,将对象通过网络传输到另一台电脑上。
序列化和反序列化
当两个进程远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列化的形式在网络上传送。比如我们可以通过http协议发送字符串信息;我们也可以在网络上直接发送Java对象,发送方需要把这个Java对象转化为字节序列(序列化),才能在网络上传送;接收方则需要把字节序列再恢复为Java对象(反序列化)才能正常对象才能读取。
把Java对象转化为字节序列的过程称为对象的序列化。把字节序列恢复为Java对象的过程称为对象的反序列化。
对象序列化的作用:
- 持久化:把对象的字节序列永久的保存在硬盘上。通常存放在一个文件中。
- 网络通信:在网络上传送对象的字节序列。比如:服务器之间的数据通信、对象传递。
序列化涉及的接口和类
类
- ObjectOutputStream
代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到目标输出流中。 - ObjectInputStream
代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
接口
只有实现Serializable接口的类的对象才能被序列化。Serializable接口是一个口接口,只起到标记作用。
使用对象流既可以对基本数据类型读写,也可以对Java对象进行读写操作。
ObjectOutputStream和ObjectInputStream
使用这两个流对基本数据类型以及字符串数据类型的读取是和数据流对基本数据类型和字符串数据类型的读取时一样的方法名字一样没在读时也要按照写的顺序来读取。我们直接用这两个流来操作Java对象,先看将对象序列化到文件的例子:
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamDome {
public static void main(String[] args) {
ObjectOutputStream oos=null;
try{
oos=new ObjectOutputStream(new FileOutputStream("e:/222.txt")); //将对象序列化到文件中的桥梁
User users=new User(123,"你好IO",19); //创建对象
oos.writeObject(users); //通过writeObject()方法将对象序列化到文件中去
oos.flush();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (oos!=null)
oos.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
这样就将一个对象序列化到一个文件当中了。
上述类中使用的Users类:
import java.io.Serializable;
public class User implements Serializable {
private int userId;
private String userName;
private int userAge;
public User(int userId, String userName, int userAge) {
this.userId = userId;
this.userName = userName;
this.userAge = userAge;
}
public User() {}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
}
在这个类中要实现Serializable接口,否则会抛出异常。
接下来将对象从文件中反序列化:
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class ObjectInputStreamDome {
public static void main(String[] args) {
ObjectInputStream ois=null;
try{
ois=new ObjectInputStream(new FileInputStream("e:/222.txt"));
User user=(User)ois.readObject(); //将对象反序列化然后强转为User类型
System.out.println(user.getUserAge()+"\t"+user.getUserId()+"\t"+user.getUserName());
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (ois!=null){
ois.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
输出结果: