Stream
- Java程序得到数据是输入流
- Java程序对外提供数据是输出流
- 输入和输出是以Java程序为核心的
流的分类
- 输入流和输出流
1.inputStream类是输入流的基类
2.OutputSream类是输出流的基类 - 字节流和字符流
1.字节流的类名字都包含Stream
2.字符流的类名中包含Reader或Writer - 转换流
1.以字符流读取字节流
2.以字符流写入字节流 - 随机访问流:RandomAccessFile
- 缓存流:利用缓冲区提示性能
- 对象流:对象流就是序列化和反序列化
- 数据流:数据流就是将指定的数据类型读取和写入
设计原则
Java的I/O库提供了一种称作链接的机制,可以将一个流与另一个流首尾相连,形成一个流管道的链接,通过流的链接,可以动态地增加流的功能,而这种功能的增加是通过组合一些流的基本功能而动态获取的。
流的操作流程
不管是输入流还是输出流,操作过程包括如下:
第一步:打开流:通过File类或者网络或者其他打开流
第二步:操作流:读写流
第三步:关闭流:以释放和这个流相关的系统资源
字节流
字节流是由字节组成的,是byte类型
字节流是采用ASCII编码的
字节流主要用在处理二进制数据(图像,word等各种文件都是二进制的),是按字节来处理的,但实际中很多的数据是文本。
字节流的类体系结构如下图:
字节输出流OutputStream
OutputStream此抽象类,是表示输出字节流的所有类的超类。操作的数据都是字节,定义了输出字节流的基本共性功能方法。
输出流中定义都是写write方法。
返回值 | 方法名 | 描述 |
---|---|---|
void |
close() |
关闭此输出流并释放与此流相关联的任何系统资源。 |
void |
flush() |
刷新此输出流并强制任何缓冲的输出字节被写出。 |
void |
write(byte[] b) |
将 b.length 字节从指定的字节数组写入此输出流。 |
void |
write(byte[] b,int off,int len) |
从指定的字节数组写入 len 个字节,从偏移 off 开始输出到此输出流。 |
void |
write(int b) |
将指定的字节写入此输出流。 |
FileOutputStream类
OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件。FileOutputStream类,即文件输出流,是用于将数据写入 File的输出流。
返回值 | 方法名 | 描述 |
---|---|---|
void |
close() |
关闭此文件输出流并释放与此流相关联的任何系统资源。 |
void |
write(byte[] b) |
将 b.length 个字节从指定的字节数组写入此文件输出流。 |
void |
write(byte[] b, int off, int len) |
将 len 字节从位于偏移量 off 的指定字节数组写入此文件输出流。 |
void |
write(int b) |
将指定的字节写入此文件输出流。 |
#FileOutputStream类写入数据到文件中
public static void main(String[] args) throws IOException {
//需求:将数据写入到文件中。
//创建存储数据的文件。
File file = new File("d:\\file.txt");//覆盖
//File file = new File("d:\\file.txt",true);//第二个参数true,表示追加模式
//创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
//输出流目的是文件,会自动创建。如果文件存在,则覆盖。
FileOutputStream fos = new FileOutputStream(file);
//调用父类中的write方法。
byte[] data = "abcde".getBytes();
fos.write(data);
//关闭流资源。
fos.close();
}
给文件中续写和换行
我们直接new FileOutputStream(file)这样创建对象,写入数据,会覆盖原有的文件,那么我们想在原有的文件中续写内容怎么办呢?
查阅FileOutputStream的API。发现在FileOutputStream的构造函数中,可以接受一个boolean类型的值,如果值true,就会在文件末位继续添加。
构造函数 | 说明 |
---|---|
FileOutputStream(File file) |
创建文件输出流以写入由指定的 File 对象表示的文件。 |
FileOutputStream(File file, boolean append) |
创建文件输出流以写入由指定的 File 对象表示的文件。 |
FileOutputStream(FileDescriptor fdObj) |
创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。 |
FileOutputStream(String name) |
创建文件输出流以指定的名称写入文件。 |
FileOutputStream(String name, boolean append) |
创建文件输出流以指定的名称写入文件。 |
:要在finally中关闭流
public static void main(String[] args) {
File file = new File("d:\\file.txt");
//定义FileOutputStream的引用
FileOutputStream fos = null;
try {
//创建FileOutputStream对象
fos = new FileOutputStream(file);
//写出数据
fos.write("abcde".getBytes());
} catch (IOException e) {
System.out.println(e.toString() + "----");
} finally {
//一定要判断fos是否为null,只有不为null时,才可以关闭资源
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException("");
}
}
}
}
字节输入流InputStream
InputStream 用于从源头(通常是文件)读取数据(字节信息)到内存中,java.io.InputStream 抽象类是所有字节输入流的父类。
返回值 | 方法名 | 说明 |
---|---|---|
void |
close() |
关闭此输入流并释放与流相关联的任何系统资源。 |
int |
read() |
从输入流读取数据的下一个字节。 |
int |
read(byte[] b) |
从输入流读取一些字节数,并将它们存储到缓冲区 b 。 |
int |
read(byte[] b, int off, int len) |
从输入流读取最多 len 字节的数据到一个字节数组。 |
FileInputStream类
InputStream有很多子类,其中子类FileInputStream可用来读取文件内容。
FileInputStream 从文件系统中的某个文件中获得输入字节。
构造函数 | 说明 |
---|---|
FileInputStream(File file) |
通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File 对象 file 命名。 |
FileInputStream(String name) |
通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name 命名。 |
FileInputStream类读取数据read方法
返回值 | 方法名 | 说明 |
---|---|---|
void |
close() |
关闭此文件输入流并释放与流相关联的任何系统资源。 |
int |
read() |
从该输入流读取一个字节的数据。 |
int |
read(byte[] b) |
从该输入流读取最多 b.length 个字节的数据为字节数组。 |
int |
read(byte[] b, int off, int len) |
从该输入流读取最多 len 字节的数据为字节数组。 |
public static void main(String[] args) throws IOException {
File file = new File("d:\\file.txt");
//创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
FileInputStream fis = new FileInputStream(file);
//读取数据。使用 read();一次读一个字节。
int ch = 0;
while ((ch = fis.read()) != -1) {
System.out.println("ch=" + (char) ch);
}
// 关闭资源。
fis.close();
}
读取数据read(byte[])方法
在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的read方法,一次可以读取多个字符。
public static void main(String[] args) throws IOException {
//演示第二个读取方法, read(byte[]);
File file = new File("d:\\file.txt");
// 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
FileInputStream fis = new FileInputStream(file);
//创建一个字节数组。
byte[] buf = new byte[1024];//长度可以定义成1024的整数倍。
int len = 0;
while((len=fis.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
fis.close();
}
读取数据read(byte[])方法
在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的read方法,一次可以读取多个字符。
public static void main(String[] args) throws IOException {
//演示第二个读取方法, read(byte[]);
File file = new File("d:\\file.txt");
// 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
FileInputStream fis = new FileInputStream(file);
//创建一个字节数组。
byte[] buf = new byte[1024];//长度可以定义成1024的整数倍。
int len = 0;
while((len=fis.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
fis.close();
}
中多个数据都读进内容中,然后在一次写出去,这样的速度一定会比前面代码速度快。
public static void main(String[] args) throws IOException {
File srcFile = new File("d:\\images\\test.JPG");
File destFile = new File("copyTest.JPG");
// 明确字节流 输入流和源相关联,输出流和目的关联。
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
//定义一个缓冲区。
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);// 将数组中的指定长度的数据写入到输出流中。
}
// 关闭资源。
fos.close();
fis.close();
}
使用字节缓存流提升性能
字节缓冲流根据流的方向,共有2个
- 写入数据到流中,字节缓冲输出流 BufferedOutputStream
- 读取流中的数据,字节缓冲输入流 BufferedInputStream
它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了IO流的读写速度
字节缓冲输出流BufferedOutputStream
构造函数 | 说明 |
---|---|
BufferedOutputStream(OutputStream out) |
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 |
BufferedOutputStream(OutputStream out, int size) |
创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。 |
字节缓冲输入流 BufferedInputStream
构造函数 | 说明 |
---|---|
BufferedInputStream(InputStream in) |
创建一个 BufferedInputStream 并保存其参数,输入流 in ,供以后使用。 |
BufferedInputStream(InputStream in, int size) |
创建 BufferedInputStream 具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用。 |
字符流
- 字符流是由字符组成的
- 字符由两个字节组成。1字符=2字节
- 字符采用Unicode编码
- 字符流支持中文,支持String类型
字符流的类体系结构如下:
字符编码表
计算机底册数据存储都是二进制数据,每一个子符和一个整数对应起来,就形成了一张表
也叫编码表:生活中字符和计算机二级制的对应关系表。
- ASCII
- ISO-8859-1
- GB2312
1.GBK
2.GBK18030 - UNICODE
- UTF-8
字符输入流Reader
上述程序中我们读取拥有中文的文件时,使用的字节流在读取,那么我们读取到的都是一个一个字节。只要把这些字节去查阅对应的编码表,就能够得到与之对应的字符。
API中已经给我们提供了读取相应字符的功能流对象,Reader,读取字符流的抽象超类。
返回值 | 方法名 | 说明 |
---|---|---|
int |
read() |
读一个字符 |
int |
read(char[] cbuf) |
将字符读入数组。 |
abstract int |
read(char[] cbuf, int off, int len) |
将字符读入数组的一部分。 |
FileReader类
FileReader类是Reader类的子类,FileReader是用于读取字符流。
构造函数 | |
---|---|
FileReader(File file) |
创建一个新的 FileReader ,给出 File 读取。 |
FileReader(String fileName) |
创建一个新的 FileReader ,给定要读取的文件的名称。 |
FileReader读取包含中文的文件
public static void main(String[] args) throws IOException {
//给文件中写中文
writeCNText();
//读取文件中的中文
readCNText();
}
//读取中文
public static void readCNText() throws IOException {
FileReader fr = new FileReader("D:\\cn.txt");
int ch = 0;
while((ch = fr.read())!=-1){
//输出的字符对应的编码值
System.out.println(ch);
//输出字符本身
System.out.println((char)ch);
}
}
//写中文
public static void writeCNText() throws IOException {
FileOutputStream fos = new FileOutputStream("D:\\cn.txt");
fos.write("我是中文".getBytes());
fos.close();
}
运行结果
25105
我
26159
是
20013
中
25991
文
字符输出流Writer
既然有专门用于读取字符的流对象,那么肯定也有写的字符流对象,Writer类就是专门写字符流的对象,是写入字符流的抽象类。
返回值 | 方法名 | 说明 |
---|---|---|
abstract void |
close() |
关闭流,先刷新。 |
abstract void |
flush() |
刷新流。 |
void |
write(char[] cbuf) |
写入一个字符数组。 |
abstract void |
write(char[] cbuf, int off, int len) |
写入字符数组的一部分。 |
void |
write(int c) |
写一个字符 |
void |
write(String str) |
写一个字符串 |
void |
write(String str, int off, int len) |
写一个字符串的一部分。 |
FileWriter类
FileWriter类是Writer类的子类,FileWriter 类用于写入字符流的抽象类。
构造函数 | |
---|---|
FileWriter(File file) |
给一个File对象构造一个FileWriter对象。 |
FileWriter(File file, boolean append) |
给一个File对象构造一个FileWriter对象。 |
FileWriter(String fileName) |
构造一个给定文件名的FileWriter对象。 |
FileWriter(String fileName, boolean append) |
构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。 |
FileWriter写入中文到文件中
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("d:\\fw.txt");
//FileWriter fw = new FileWriter("d:\\fw.txt",true);//第二个参数true,表示追加模式
fw.write("山香红叶时叶红香山");//这些文字都要先编码。都写入到了流的缓冲区中。
fw.flush();
fw.close();
}
flush()和close()的区别
- flush:将流中缓冲区缓冲的数据刷新到新的目的地中,刷新后,流任然可以使用
- close():关闭资源,关闭前会将缓冲区的数据刷新到目的地,否自丢失数据,然后再关闭流。流不可以再使用
使用字符缓存流提升性能
字符缓冲输入流BufferedReader
- BufferedReader 类从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。
构造方法 | |
---|---|
BufferedReader(Reader in) |
创建使用默认大小的输入缓冲区的缓冲字符输入流。 |
BufferedReader(Reader in, int sz) |
创建使用指定大小的输入缓冲区的缓冲字符输入流。 |
返回值 | 方法名 | 说明 |
---|---|---|
void |
close() |
关闭流并释放与之相关联的任何系统资源。 |
int |
read() |
读一个字符 |
int |
read(char[] cbuf, int off, int len) |
将字符读入数组的一部分。 |
String |
readLine() |
读一行文字。 |
字符缓存输出流BufferedWriter
- 将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。
构造函数 | 说明 |
---|---|
BufferedWriter(Writer out) |
创建使用默认大小的输出缓冲区的缓冲字符输出流。 |
BufferedWriter(Writer out, int sz) |
创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。 |
返回值 | 方法名 | 说明 |
---|---|---|
void |
close() |
关闭流,先刷新。 |
void |
flush() |
刷新流。 |
void |
newLine() |
写一行行分隔符。 |
void |
write(char[] cbuf, int off, int len) |
写入字符数组的一部分。 |
void |
write(int c) |
写一个字符 |
void |
write(String s, int off, int len) |
写一个字符串的一部分。 |
转换流
OutputStreamWrite
OutputStreamWriter 是 Writer子类,是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节。它的作用的就是,将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去。
构造函数 | |
---|---|
OutputStreamWriter(OutputStream out) |
创建一个使用默认字符编码的OutputStreamWriter。 |
OutputStreamWriter(OutputStream out, Charset cs) |
创建一个使用给定字符集的OutputStreamWriter。 |
返回值 | 方法名 | 说明 |
---|---|---|
void |
close() |
关闭流,先刷新。 |
void |
flush() |
刷新流。 |
String |
getEncoding() |
返回此流使用的字符编码的名称。 |
void |
write(char[] cbuf, int off, int len) |
写入字符数组的一部分。 |
void |
write(int c) |
写一个字符 |
void |
write(String str, int off, int len) |
写一个字符串的一部分。 |
public static void main(String[] args) throws IOException {
File file = new File("haha1.txt");
FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
BufferedWriter bw = new BufferedWriter(osw);
bw.write("上海自来水来自海上");
bw.flush();
bw.close();
}
在OutputStreamWriter流中维护自己的缓冲区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到OutputStreamWriter缓冲区中。然后再调用刷新功能,或者关闭流,或者缓冲区存满后会把缓冲区中的字节数据使用字节流写到指定的文件中。
InputStreamReader类
构造函数 | |
---|---|
InputStreamReader(InputStream in) |
创建一个使用默认字符集的InputStreamReader。 |
InputStreamReader(InputStream in, Charset cs) |
创建一个使用给定字符集的InputStreamReader。 |
返回值 | 方法名 | 说明 |
---|---|---|
void |
close() |
关闭流并释放与之相关联的任何系统资源。 |
String |
getEncoding() |
返回此流使用的字符编码的名称。 |
int |
read() |
读一个字符 |
int |
read(char[] cbuf, int offset, int length) |
将字符读入数组的一部分。 |
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(
new File("haha1.txt")),"gbk"));
String s = br.readLine();
System.out.println(s);
br.close();
}
注意:在读取指定的编码的文件时,一定要指定编码格式,否则就会发生解码错误,而发生乱码现象
字节流与字符流的区别
字节流以字节为单位输入输出,8位二进制数
字符流以字符位单位输入输出,16二进制数
数据流
DateInputStream和DateInputStre提供读写Java中基本数据的功能。
在程序中写入字符串使用的是writeUTF方法,读取字符串使用的是readUTF方法,这两个方法是配对使用的。
DataInputStream
- 数据输入流允许应用程序以独立于机器的方式从底层输入流读取原始Java数据类型。 应用程序使用数据输出流来写入稍后可以被数据输入流读取的数据。
构造函数 | |
---|---|
DataInputStream(InputStream in) |
创建使用指定的底层InputStream的DataInputStream。 |
返回值 | 方法名 | |
---|---|---|
int |
read(byte[] b) |
从包含的输入流中读取一些字节数,并将它们存储到缓冲区数组 b 。 |
int |
read(byte[] b,int off,int len) |
从包含的输入流读取最多 len 个字节的数据为字节数组。 |
boolean |
readBoolean() |
见的总承包 readBoolean 的方法 DataInput 。 |
byte |
readByte() |
见的总承包 readByte 的方法 DataInput 。 |
char |
readChar() |
见 readChar 方法的总合同 DataInput 。 |
double |
readDouble() |
见 readDouble 方法 DataInput 的总体合同。 |
float |
readFloat() |
见 readFloat 法 DataInput 的一般合同。 |
int |
readInt() |
见 readInt 方法 DataInput 的一般合同。 |
long |
readLong() |
见的总承包 readLong 的方法 DataInput 。 |
short |
readShort() |
见 readShort 方法 DataInput 的一般合同。 |
String |
readUTF() |
见 readUTF 法 DataInput 的一般合同。 |
DataOutputStream
- 数据输出流使应用程序以便携式方式将原始Java数据类型写入输出流。 然后应用程序可以使用数据输入流来读取数据。
构造函数 | |
---|---|
DataOutputStream(OutputStream out) |
创建一个新的数据输出流,以将数据写入指定的底层输出流。 |
返回值 | 方法名 | 说明 |
---|---|---|
void |
flush() |
刷新此数据输出流。 |
int |
size() |
返回计数器的当前值 written ,到目前为止写入此数据输出流的字节数。 |
void |
write(byte[] b, int off, int len) |
写入 len 从指定的字节数组起始于偏移 off 基础输出流。 |
void |
write(int b) |
将指定的字节(参数 b 的低8位)写入底层输出流。 |
void |
writeBoolean(boolean v) |
将 boolean 写入底层输出流作为1字节值。 |
void |
writeByte(int v) |
将 byte 作为1字节值写入底层输出流。 |
void |
writeBytes(String s) |
将字符串作为字节序列写入基础输出流。 |
void |
writeChar(int v) |
将 char 写入底层输出流作为2字节值,高字节优先。 |
void |
writeChars(String s) |
将字符串写入底层输出流作为一系列字符。 |
void |
writeDouble(double v) |
双参数传递给转换 long 使用 doubleToLongBits 方法在类 Double ,然后写入该 long 值基础输出流作为8字节的数量,高字节。 |
void |
writeFloat(float v) |
浮子参数的转换 int 使用 floatToIntBits 方法在类 Float ,<br />然后写入该 int 值基础输出流作为一个4字节的数量,高字节。 |
void |
writeInt(int v) |
将底层输出流写入 int 作为四字节,高位字节。 |
void |
writeLong(long v) |
将 long 写入底层输出流,为8字节,高字节为首。 |
void |
writeShort(int v) |
将 short 写入底层输出流作为两个字节,高字节优先。 |
void |
writeUTF(String str) |
使用 modified UTF-8 编码以机器无关的方式将字符串写入基础输出流。 |
持久化保存对象状态
public class Student {
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/**
* 需求:将对象的属性值写入到文件中保存
* DataOutputStream是专门读写基本类型和String类型
*/
public class DataOutputSteamDemo {
public static void main(String[] args) throws IOException {
Student s[] = {
new Student("sunmer", 100),
new Student("华夏", 80)
};
File file =new File("d:/data.txt");
FileOutputStream fos =new FileOutputStream(file);
BufferedOutputStream bos =new BufferedOutputStream(fos);
DataOutputStream dos = new DataOutputStream(bos);
for (int i = 0; i < s.length; i++) {
dos.writeUTF(s[i].getName());
dos.writeInt(s[i].getAge());
}
dos.close();
bos.close();
fos.close();
}
}
/**
* 需求:将对象的属性值从文件中读取回来,重新构建对象
* DataInputStream是专门读写基本类型和String
*/
public class DataInputStreamDemo {
public static void main(String[] args) throws Exception {
File file =new File("d:/data.txt");
FileInputStream fis =new FileInputStream(file);
BufferedInputStream bis =new BufferedInputStream(fis);
DataInputStream dis =new DataInputStream(bis);
String name1 = dis.readUTF();
int age1 = dis.readInt();
Student s1 = new Student(name1, age1);
String name2 = dis.readUTF();
int age2 = dis.readInt();
Student s2 = new Student(name2, age2);
dis.close();
bis.close();
fis.close();
System.out.println(s1);
System.out.println(s2);
}
}
对象流(序列化和反序列化)
ObjectOutputStream和ObjectInputStream
Java中的对象在程序运行期间保存在内存中,当程序运行结束,JVM退出,进程的地址空间被清理,所有对象都会被清除。
所以我们需要使用对象流来保存对象的状态**(状态:对象的属性名称和属性值)
序列化:将对象的属性名称和属性值保存到文件中存储
反序列化:将对象从文件中读取回内存,还原对象
对象序列化流ObjectOutputStream
ObjectOutputStream是FileOutputStream的子类,用于实现序列化,即向输出流中写入对象。
构造方法 | ||
---|---|---|
protected |
ObjectOutputStream() |
返回值 | 方法名 | 说明 |
---|---|---|
void |
writeObject(Object obj) |
将指定的对象写入ObjectOutputStream。 |
反序列化对象流ObjectInputStream
ObjectInputStream是InputStream的子类,用于反序列化,即从输入流中读取对象。
使用反序列化来恢复对象时,必须还必须能够找到该对象所属类的字节码文件。
构造函数 | ||
---|---|---|
protected |
ObjectInputStream() |
返回值 | 方法名 | 说明 |
---|---|---|
Object |
readObject() |
从ObjectInputStream读取一个对象。 |
序列化接口Serializable
当一个对象要能被序列化,这个对象所属的类必须实现Serializable接口。否则会发生异常NotSerializableException异常。
Serializable接口是一个空接口,里面没有定义任何成员。该接口给需要序列化的类,提供了一个序列版本号,serialVersionUID。该版本号的目的在于验证序列化的对象和对应类是否版本匹配。
序列化对象
序列化Worker对象
public class Worker implements Serializable{
private String name;
private int age;
public Worker(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Worker{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/**
* 序列化
* 注意:需要序列化的对象必须实现Serializable接口
*
*/
public class ObjectOutputStreamDemo {
public static void main(String[] args) {
write();
}
private static void write() {
File file =null;
FileOutputStream fos =null;
BufferedOutputStream bos =null;
ObjectOutputStream oos =null;
try {
file = new File("d:/data.yfq");
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
oos = new ObjectOutputStream(bos);
Worker w1 = new Worker("时传祥", 20);
Worker wc = new Worker("王进喜", 21);
oos.writeObject(w1);
oos.writeObject(wc);
oos.flush();
System.out.println("序列化结束");
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
反序列化对象
/**
* 反序列化
*/
public class ObjectInputSteamDemo {
public static void main(String[] args) {
read();
}
private static void read() {
File file = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
ObjectInputStream ois = null;
try {
file = new File("d:/data.yfq");
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
ois = new ObjectInputStream(bis);
Worker w1 = (Worker)ois.readObject();
System.out.println(w1);
Worker wc = (Worker)ois.readObject();
System.out.println(wc);
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
瞬态关键字transient
当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient修饰。只要被transient修饰了,序列化时这个属性就不会被序列化了。
同时静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。
随机访问流(RandomAccessFile)
只对文件进行读写操作,使用RandomAccessFile会更加方便。这个类与输入输出流没有关系,是直接Object继承的。
-
public long getFilePointer() throws IOException
要移动文件指针,可以调用seek方法,该方法的签名如下所示:
-
public void seek(long pos) throws IOException
参数pos是偏移的位置从文件开头、以字节为单位来测量。
除了基本的读写方法外,RandomAccessFile也支持对Java基本数据类型的读写操作。RandomAccessFile类在构造时,需要指定文件的访问模式。
除了基本的读写方法外,RandomAccessFile也支持对Java基本数据类型的读写操作。RandomAccessFile类在构造时,需要指定文件的访问模式。
关于临时文件:
temp目录是临时目录
开发中建议用tmp表示临时目录,或者临时文件的文件名的开头。