------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
一、对象的可串行化
1、概述
有时我们需要将程序运行过程中产生的某个类对象保存下来,下次程序运行时通过读入保存的数据可以恢复这个对象。由于对象是运行时期的产物,因此对象读写需要java虚拟机的底层支持,这在java中称作是对象的可串行化。即:将堆中的对象序列化,对象的可串行化又叫做对象的持久化存储
2、串行化读取对象ObjectInputStream
构造函数
protectedObjectInputStream()
protected ObjectInputStream(InputStream in)
3、串行化写出对象ObjectOutputStream
构造函数protectedObjectOutputStream()
protectedObjectOutputStream(OutputStream out)
注:这两个功能需要成对使用。即用ObjectOutputStream写的对象只能用ObjectInputStream读取,并且只能用于操作字节流。
4 、可串行化的前提
被操作的类首先需要实现Serializable接口。类通过实现此接口才可以被序列化,此接口中无任何方法,所以无需复写(此接口为“标记接口”)。
无方法的接口被称为“标记接口”,每一个实现此接口的类都会被系统自动加上特定的标记,当然也可以自定义标记。
类的固定标识:ID号:定义方法 static final long seriversionUID= 42L;
静态数据不能被串行化。只有堆中的数据才可被串行化,此数据在方法区中。
另外被关键字transient修饰的非静态数据也不可以被串行化。
注意:
当串行类没有自定义的ID号的时候,若改动类中的任意代码则此类的ID也会 随之而改变,当然不可以被原来的代码调用,若想随意改动此类中的代码,而且改动后还想继续能被原代码调用的话,只能自定义ID号后才可以。
5、 常用方法
其中读取和写入的方法十分强大,可以读取和写入任意类型的数据,所以在这里只介绍两对特殊的方法:
1、Object writeObj()和Object readObj(); 可直接操作类对象
2、void writeUTF(String str),StringreadUTF() 编码表UTF-8 修改版
一般存储文件的后缀名命名为object。
代码示例:经person类的对象存储到文本文档中
二、管道流
1、概述
管道流是IO流中可以和线程结合使用的流。
一般的IO流进行读写操作时我们需要一个中转站进行相互之间的链接,但是管道流不需要中转站,可以直接将输入输出进行连接。
应用时管道输入流应该连接到管道出输出流;管道输入流提供要写入管道输出流的所有字节数据,一般情况下数据由某个线程从PipedInputStream对象中读取,并由其他线程将其写入到 应的PipedOutputStream对象中。不建议对这两个对象尝试使用单个线程;因为这样可能会死锁线程。
2、管道读取流PipedInputStream
常用的构造函数:
PipedInputStream(PipedOutputStream src)
常用的方法:
int available()获得数据长度
void close()
void connect(PipedOutputStream src) 将两个管道流链接起来
int read()
int read(byte[] b,int off, int len)
3、管道写出流PipedOutputStream
常用的构造函数:
PipedOutputStream(PipedInputStream snk)
常用的方法:
void close()
void connect(PipedInputStream snk)
void flush()
void write(int b)
void write(byte[] b,int off, int len)
代码示例:
运行结果为:
三、RandomAccessFile(随机读写访问)
1、概述
此类直接继承Object();此类的实例支持对随机访问文件的读取和写入;随机访问文件的行为类似存储在文件系统中的一个大型byte数组。并且存在指向该隐函数组的光标或索引,称为文件指针:输入操作从文件指针开始读取字节,并随着对字节的读取而前移文件指针。该文件指针可以通过getFilePoint()方法读取,并通过seek()方法和skipBytes(int x)方法改变指针的位置,该类的特殊之处就是可以通过指针指定任意位置进行操作。
2、构造方法
RandomAccessFile(File file,String mode);
RandomAccessFile(Stringname,String mode)
通过构造函数可以看出,该类只能操作文件
操作文件的模式:只读r,读写rw等。
若模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
若模式rw。当操作的文件不存在时,会自动创建。如果存在则不会覆盖
3、常用方法
3.1、读方法
readInt() 一次读一个有符号的32位整数。
read(byte[] b),read (byte[] b,int off,intlen),readChar,readDouble,readByte,readBoolean,readFloat,readLong,readLine();
3.2、写方法
writeInt,按四个字节将int写入文件,先写高位。
write(byte[]b); write(int b); write(byte[] b,int off,int len); write, writeChar,writeDouble,writeChars,writeByte,writeBoolean,writeFloat,writeLong,
3.3、seek(int x) 设置对象指针位置(最好数据是有规律的)
3.4、skipBytes(int x) 跳过指定字节数(只能往前调,不能往后跳)
3.5、getFilePointer 获取当前指针位置
3.6、long length() 返回此文件中的当前偏移量。
这个类最牛的地方就是可以通过指针可以往数组中的任意位置上进行读写操作,还可以对指针指定的数据进行修改。
可以实现数据的分段写入,通过指针将整个区域分为若干个段,每个段都有一个线程负责写入,每个线程之间没有关系。此为下载软件原理。
代码示例:
四、操作基本数据类型的流对象DataStream
4.1、概述
此类是专门用于操作基本数据的流对象,所以只能操作字节流; 4.2、数据读取DataInputStream
构造函数:DataInputStream(InputStream in) 创建一个接收字节流
常用的方法:
4.2、读方法
String readUTF(),使用UTF-8的修改版编码表读数据
static StringreadUTF(DataInput in)
readChar,readDouble,readByte,readBoolean,readFloat,readLong,
4.3、数据写入DataOutputStream
构造函数:
DataOutputStream(OutputStream out) 创建一个写出字节流
常用的方法
写方法
void writeUTF(),使用UTF-8的修改版编码表写数据
write, writeChar,writeDouble,writeChars,writeByte,writeBoolean,writeFloat,writeLong,
void flush()
int size()
从以上方法可以看出来:这个类中的读方法和写方法非常强大。
代码示例:
五、操作字节数组
1、概述
此类是专门用于操作字节数组的IO流;并且包含一个内部缓冲区;此流对象不使用系统的底层资源可以直接在内存中完成数据的操作,所以close关闭是无效的,在关闭此流后仍可被调用,并且不会产生任何异常。
2、读取流ByteArrayInputStream
构造函数
ByteArrayInputStream(byte[] buf)
ByteArrayInputStream(byte[] buf, int offset, int length)
ByteArrayInputStream在构造的时候,需要接收数据源,而且数据源是一个字节数组。
常用方法
intread()读取一个字节;
3、写出流ByteArrayOutputStream
构造函数
ByteArrayOutputStream(int size) //可以指定缓冲区的容量
ByteArrayOutputStream在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组,这个数组就是数据目的地,缓冲区随着数据的不断写入而自动增长。而且可以使用toByteArray()和toString()获取数据。
常用方法
int size() 返回当前缓冲区大小;
byte[]toByteArray()创建一个新分配的 byte 数组。
String toString() 按照默认的编码表将缓冲区内容转换为字符串
String toString(String charsetName) 指定的编码表进行编码
void writeTo(OutputStreamout);将此数组中的数据写入到一个输出流当中。注意:此方法会抛出IOException异常。
六、流操作规律讲解
源设备: 键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备: 控制台 System.out,硬盘FileStream,内存 ArrayStream。
代码示例:
运行结果:
七、操作字符数组CharArrayReader与CharArrayWrite
概述和方法与操作字节数组相同,只是操作对象不同而已。
请自行查看API文档。
八、操作字符串StringReader 与StringWriter
概述和方法与操作字节数组相同,只是操作对象不同而已。
请自行查看API文档。
九、字符编码
ASCII:美国标准信息交换码。用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
nicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java·语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符。
编码:字符串变成字节数组。
解码:字节数组变成字符串。
变成二进制:Interger.toBinaryString(对象)
字符变字节方法:Stringàbyte[]: str.getBytes();
字节变字符方法:Byte[]àString: new String(byte[]);
常用方法:
String(byte[] bytes); 按照默认字符集将字节变成字符串
String(byte[] bytes,String charseName(字符集));按照指定字符集将字节变成字符串
getBytes(); 按照默认的字符集进行编码
getBytes(String charseName) 按照指定的字符集进行编码
注意:
“中文”—>(BGK编码)—>(ISO8859—1解码)—>乱码” —>(ISO8859—1编码)—>(BGK解码)—>“中文”;这种方法可以,因为两张码表里含有的编码完全不一样;如果有两张都含有中文的编码表进行两次编码解码的话就会产生错误;因为源码已经被改变,原因就是两张码表里面的编码有相同之处。
小练习:
1、按照指定编码表将进行文件的写入和读取操作
代码示例:
1、按照指定编码表将字符和字节进行转换
代码示例:
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------