------- android培训、java培训、期待与您交流! ----------
day21 IO
1、对象的序列化:
ObjectInputStream和ObjectOutputStream成对使用。ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。
ObjectOutputStream(OutputStream out):创建写入指定 OutputStream 的 ObjectOutputStream。
void writeObject(Object obj):将指定的对象写入 ObjectOutputStream。只能将支持 java.io.Serializable 接口的对象写入流中。
这个方法会抛出以下异常:
IOException - 由底层 OutputStream 抛出的任何异常。
InvalidClassException - 序列化操作使用的类出了问题。
NotSerializableException - 某个要序列化的对象不能实现 java.io.Serializable 接口。
Serializable是标记接口(没有方法的接口)。
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException。可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID:static final long serialVersionUID = 42L;
若不想序列化对象中的某些非静态成员可以加修饰符transient,保证了其值在堆内存中存在,而不在文本文件中存在。 参见ObjectStreamDemo.java和Person.java
类中的静态变量不会被序列化,因为静态变量在方法区当中,仅序列化堆内存中的数据。
2、集合当中涉及到IO流的是Properties,而IO流中涉及到多线程的是管道流。
管道流两种连接方式:
一种是通过构造函数:PipedInputStream(PipedOutputStream src):创建 PipedInputStream,使其连接到管道输出流 src。
另外一种是通过方法:void connect(PipedOutputStream src):使此管道输入流连接到管道输出流 src。 参见PipedStreamDemo.java
3、RandomAccessFile:随机访问文件,自身具备读和写的方法。
该类不算是IO体系中子类,而是直接继承自Object。但是它是IO包中成员,因为它具备读和写功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。
其实完成读写的原理就是内部封装了字节输入流和输出流。
通过构造函数可以看出:该类只能操作文件,而且操作文件还有模式:只读r,读写rw等。
如果模式为只读 r:不会创建文件,会去读取一个已存在文件,如果该文件不存在,则会出现异常。如果模式为rw:若操作的文件不存在,会自动创建。如果已存在则不会覆盖。
raf.seek(8*1); //调整对象中指针。从文件开头以字节为单位测量的偏移量位置,在该位置设置文件指针
raf.skipBytes(8); //跳过指定的字节数 参见RandomAccessFileDemo.java
4、DataInputStream与DataOutputStream可以用于操作基本数据类型数据的流对象。
参见DataStreamDemo.java
5、用于操作字节数组的流对象:
ByteArrayInputStream :在构造的时候,需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。这就是数据目的地。
因为这两个流对象都操作的数组,并没有使用系统资源。所以,不用进行close关闭。
在流操作规律讲解时:
源设备: 键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备:控制台 System.out,硬盘FileStream,内存 ArrayStream。
用流的读写思想来操作数据。
6、字符编码:
编码:字符串变成字节数组。String-->byte[]:str.getBytes(charsetName);
解码:字节数组变成字符串。byte[] -->String:new String(byte[],charsetName);
常见的编码表有:
ASCII码:美国标准信息交换码,用一个字节的7位表示
ISO8859-1:拉丁码表,用一个字节的8位表示
GB2312:中国的中文编码表
GBK:中国的中文编码表升级,一个中文用两个字节表示
UTF-8:最多用三个字节来表示一个字符
Unicode:国际标准码,融合了多种文字