原文出处:https://blog.csdn.net/KK_bluebule/article/details/79157404?
一、IO流简介:
流的定义:流是指一连串流动的字符,是以先进先出方式发送信息的通道。
按流向分:输出流:OutputStream和Writer为基类
输入流:InputStream和Reader为基类
按处理数据单元划分:字节流:字节输入流:InputStream基类
字节输出流:OutputStream基类
字符流:字符输入流:Reader基类
字节输出流:Writer基类
(字节流是 8 位通用字节流,字符流是16位Unicode字符流)
1.1 InputStream
引入相关的类:
InputStream ins =null;
构建输入流,例如FileInputStream:
ins =new FileInputStream(new File(path));
操控字节输入流的,所用的方法也是针对字节的。
常用方法:
返回值类型
|
方法名
|
方法简介
|
abstract int | read( ) | 从此输入流中读取下一个字节(此方法是抽象方法,子类必须实现该方法。 |
int | read(byte [ ] b ) | 从输入流中读取一定数量的字节,存储在参数指定的字节数组中。 |
int | read(byte [ ] b ,int off ,int len ) | 读到 len字节从输入流读入字节数组数据。 |
long | skip( long n ) | 跳过并丢弃 n字节从输入流中的数据。 |
int | available( ) | 返回此输入流下一个方法可以读取的字节数。 |
void | close( ) | 关闭流。 |
案例:
使用缓冲数组的方法读取文件内容,提高效率
public static void readArr() {
// 1、明确源数据源
File f = new File("F:/1/余文佳/1.txt");
// 2、构建流的对象
InputStream ins = null;
try {
ins = new FileInputStream(f);
// 3、声明缓冲数组
int i;
// 表示读取了多少个字符到数组中
byte[] bt = new byte[5];
// 字节缓冲数组
// 4、读取数据到数组中
//可以读多少写多少,转化成char类型,但是文件中都是英文,如果有中文则输出乱码
while ((i = (ins.read(bt))) != -1) {
for (int j = 0; j < i; j++) {
System.out.print((char) bt[j]);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
try {
if (ins != null) {
ins.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
tips:
关于InputStream.read(byte[] b)和InputStream.read(byte[] b,int off,int len)这两个方法都是用来从流里读取多个字节的,有经验的程序员就会发现,这两个方法经常 读取不到自己想要读取的个数的字节。比如第一个方法,程序员往往希望程序能读取到b.length个字节,而实际情况是,系统往往读取不了这么多。仔细阅读Java的API说明就发现了,这个方法 并不保证能读取这么多个字节,它只能保证最多读取这么多个字节(最少1个)。因此,如果要让程序读取count个字节,最好用以下代码:
byte[] b = new byte[count];
int readCount = 0; // 已经成功读取的字节的个数
while (readCount < count) {
readCount += in.read(bytes, readCount, count - readCount);
}
用这段代码可以保证读取count个字节,除非中途遇到IO异常或者到了数据流的结尾(EOFException)
1.2 OutputStream
常用方法:
返回值类型
|
方法名
|
方法简介
|
void | flush( ) | 刷新输出流,是缓存数据被写出来 |
void | write(byte [ ] b) | 写b.length 字节从指定的字节数组的输出流 |
void | write(byte [ ] b, int off, int len) | 写len字节从字节数组数据中到输入流 |
abstract int | write( int b ) | 将指定的字节写入该输出流中 |
void | close( ) | 关闭流 |
1.1.1 FileInputStream
FileInputStream是读取原始字节的图像数据流。读取字符流,考虑使用FileReader。
常用方法:
见InputStream中的方法
构建输入流:(准备工作)
FIle file =new File(path);
InputStream ins =null;
ins =new FileInputStream; //这里需要try catch
读取文件字符:
int i =0;
while( ( i=ins.read( ) ) != -1){
System.out.println( i );
} //输出的是自动转化的ASCII值,此处会抛出 IOException,需要try catch
或者提高效率,使用缓冲数组byte[ ] b,可读取英文文件,需要转化成char字符:
int len =0;
byte [ ]b=new byte [ 1024 ];//建立缓冲流数组
while((len=ins.read( b ))!= -1){
for( int j=0;j<len ;j++){
System.out.println( (char) bt [ j ] );
}
} //中间嵌套for循环,读多少输出多少,中文不可用,会输出乱码-->此处会抛出 IOException,需要try catch
完整案例:
package cn.pojo;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class InputStreamDemo {
public static void main(String[] args) {
readByte();
readArr();
}
/**
* 读取字节
*/
public static void readByte() {
// 1、明确源数据源
File f = new File("F:\\1\\余文佳\\1.txt");
// 2、构建输入流对象
InputStream ins = null;
try {
ins = new FileInputStream(f);
int i;
// 3、 读取文件字符
while ((i = ins.read()) != -1) {
System.out.println("i=" + i);
// 输出为转化的ascii码值
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 4、关闭资源
if (ins != null) {
try {
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
// 2、使用缓冲数组的方法读取文件内容,提高效率
public static void readArr() {
// 1、明确源数据源
File f = new File("F:/1/余文佳/1.txt");
// 2、构建流的对象
InputStream ins = null;
try {
ins = new FileInputStream(f);
// 3、声明缓冲数组
int i;
// 表示读取了多少个字符到数组中
byte[] bt = new byte[5];
// 字节缓冲数组
// 4、读取数据到数组中
while ((i = (ins.read(bt))) != -1) {
for (int j = 0; j < i; j++) {
System.out.print((char) bt[j]);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
try {
if (ins != null) {
ins.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
1.2.1 FileOutputStream
是OutputSTream的子类,主要功能是从源文件写入资料至指定文件中
构造方法:1、FileOutputStream( File file )
// 创建“File对象”对应的“文件输入流”;默认“追加模式”是false,
即“写到输出的流内容”不是以追加的方式添加到文件中。若要追加则为(File file, true);
2、FileOutputStream( String path ) /
/ 创建
“文件(路径为path)”对应的“文件输入流”;
(若没有,自动系统调用方法创建)
默认“追加模式”是false,即“写到输出的流内容”不是以追加的方式添加到文件中。
若要追加则为(String path, true);
try {
// 构造方法1
File file = new File("E:/java47.txt");
FileOutputStream fos1 = new FileOutputStream(file);
// File file = new File("E:/java47.txt");
// FileOutputStream fos1 = new FileOutputStream(file);
// 没有该文件会直接创建文件,但不能有多级目录,否则会报错,或者这只是个目录
// -->java.io.FileNotFoundException:E:\java\java48.txt (系统找不到指定的路径。)
// 构造方法2
FileOutputStream fos2 = new FileOutputStream("E:/java/java48.txt");// 规则如上
} catch (Exception e) {
e.printStackTrace();
}
常用方法:(同OutputStream)
返回值类型
|
方法名
|
方法简介
|
void | flush( ) | 刷新输出流,是缓存数据被写出来 |
void | write(byte [ ] b) | 写b.length 字节从指定的字节数组的输出流 |
void | write(byte [ ] b, int off, int len) | 写len字节从字节数组数据中到输入流 |
abstract int | write( int b ) | 将指定的字节写入该输出流中 |
void | close( ) | 关闭流 |
应用主要步骤
:1、构建字节输出流对象
2、写数据
3、关闭流
案例:
package cn.pojo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
/**
* 字节输出流案例
*
* @author kuang
*
*/
public final class OutputStreamDemo {
public static void main(String[] args) {
// 1、明确目标数据源
File f = new File("E:/java48/java48.txt");
// 判断文件是否存在,否则创建
if (!f.exists()) {
f.getParentFile().mkdirs();// 先创建目录
try {
f.createNewFile();// 再创建文件 此处需要处理异常,
} catch (Exception e) {
e.printStackTrace();
}
}
// 2、构建输出流对象(通过子类实例化父类的对象)
OutputStream outs = null ; // 首先准备好一个输出的对象
try {
outs = new FileOutputStream(f) ; // 构造方法 ,实例化,此处需要处理异常
// 执行写入文件的操作
String st = "java48班" ; // 创建字符串
byte[] bt = st.getBytes(); // 只能输出byte数组,所以将字符串变为byte数组
// 使用String st.getByte();方法
outs.write(bt); // 将内容输出,保存文件
outs.flush(); // 刷新输出流
System.out.println("写入成功!"); // 若(文件夹必须存在)没有文件,会创建文件然后写入;若文件已有相同内容,则直接覆盖
} catch (Exception e) {
e.printStackTrace();
} finally {
// 4、关闭资源
if (outs != null) {
try {
outs.close(); // 此处也要处理异常
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
Test
:
用
FileInputStream
和
FileOutputStream
实现文件的复制
package cn.pojo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class Demo {
// 检查文件是否存在,否则创建
public static void checkFile(File file) {
if (!file.exists()) {
file.getParentFile().mkdirs();// 创建多级目录
try {
file.createNewFile();// 创建文件,此处需要处理异常
System.out.println("创建文件成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// 明确源文件和目标文件
File o = new File("E:/java48/java48.txt");// 源文件
File t = new File("E:/java48/新建.txt");// 目标文件
checkFile(t);// 这里仅仅检查了目标文件
// 构建输入、输出流对象
InputStream ins = null; // 输入的对象
OutputStream outs = null; // 输出的对象
// 进行实例化,需要处理异常
try {
ins = new FileInputStream(o);// 源文件作为输入对象--->若要拼接后面加上true
outs = new FileOutputStream(t);// 目标文件作为输出对象--->若要拼接后面加上true
// 创建缓冲数组
byte[] b = new byte[1024];
int len = 0;
// 执行边读边写操作
while ((len = ins.read(b)) != -1) {
outs.write(b, 0, len);
}
// 刷新输出流
outs.flush();
// 至此复制成功
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭流(先开的后关)
try {
if (outs != null) {
// 为了避免空指针异常,进行判空
outs.close();
}
if (ins != null) {
ins.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
1.1.2 BufferedInputStream
带缓冲区的输入流,默认缓冲区大小是8M,能够减少访问磁盘的次数,提高文件读取性能;
是 FileInputStream 的子类。 实现了装饰设计模式!
BufferedInputStream没有无参构造方法,它必须传入一个InputStream(一般是FileInputStream),来一起使用,以提高读写效率。
构造方法:1、BufferInputStream(InputStream in)// 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
创建一个内部缓冲区数组并将其存储在 buf 中,该buf的大小默认为8192。
2、BufferedInputStream(InputStream in, int size)
//创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
创建一个长度为 size 的内部缓冲区数组并将其存储在 buf 中。
常用方法:
返回值类型 |
方法名
|
方法简介
|
abstract int | read( ) | 从此输入流中读取下一个字节(此方法是抽象方法,子类必须实现该方法。 |
int | read(byte [ ] b ) | 从输入流中读取一定数量的字节,存储在参数指定的字节数组中。 |
int | read(byte [ ] b ,int off ,int len ) | 读到 len字节从输入流读入字节数组数据。 |
1.2.2 BufferedOutputStream
带缓冲区的输出流,能够提高文件的写入效率。
实现了装饰设计模式!
BufferedOutputStream没有无参构造方法,它必须传入一个OutputStream(一般是FileOutputStream),来一起使用,以提高读写效率。
构造方法
:
1、BufferOutputStream(OutputStream outs)
// 创建一个 BufferedInputStream 并保存其参数,即输出流outs,将数据写入指定的基本输入流中。
2、BufferedOutputStream(OutputStream outs, int size)
//创建具有指定缓冲区大小的 BufferedOutputStream ,即输出流outs,
将数据写入指定的基本输入流中
。
常用方法
:
返回值类型
|
方法名
|
方法简介
|
void | flush( ) | 刷新输出流,是缓存数据被写出来 |
void | write(byte [ ] b) | 写b.length 字节从指定的字节数组的输出流 |
void | write(byte [ ] b, int off, int len) | 写len字节从字节数组数据中到输入流 |
Test
:
使用
BufferedInputStream
和
BufferedOutputStream
实现文件的复制
(与上面的FileInputStream Test类似)
tips:为什么要用BufferedInputStream 和 BufferedOutputStream?
优点:效率高
缺点:内存占用多
why?
不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。
带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多。
1.1.3 DataInputStream
数据
输入流
允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。 DataInputStream 对于
多线程
访问不一定是安全的。
线程安全
是可选的,它由此类方法的使用者负责。
构造方法:
DataInputStream(InputStream in);
常用方法:
返回值类型
| 方法名 |
方法简介
|
int | read(byte [ ] b) | 读取一定数量的字节从包含输入流并存入缓冲区阵列b |
int | read (byte [ ] b, int off, int len) | 读到 len 从包含输入流读入字节数组数据字节 |
boolean | readBoolean( ) | 读 true / false |
byte | readByte( ) | 读取并返回一个输入字节 |
char | readChar( ) | 读取两个字节返回一个 char 价值 |
float | readFloat( ) | 四字节读取输入并返回一个 float 价值 |
double | readDouble( ) | 八字节读取输入并返回一个 double 价值 |
int | readInt( ) | 四字节读取输入并返回一个 int 价值 |
String | readLine( ) | 从输入流读取下一行文本 |
short | readShort( ) | 两字节读取输入并返回一个 short 价值 |
String | readUTF( ) | 读取一个字符串,一直采用 modified UTF-8 编码格式 |
1.2.3 DataOutputStream
数据
输入流
允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。 DataInputStream 对于多线程访问不一定是安全的。
线程安全
是可选的,它由此类方法的使用者负责。
构造方法:
DataOutputStream( OutputStream outs);
常用方法:
返回值类型
|
方法名
|
方法简介
|
void | flush( ) | 刷新数据输出流 |
int | size( ) | 返回柜台 written 电流值,这个数据写入输出流的字节数为止 |
void | write( int b ) | 将指定的字节(论证b的低八位)的底层输出流 |
void | write( byte [ ] b, int off, int len ) | 写 len 字节指定字节数组中的起始偏移量 off 当前输出流 |
void | writeBoolean( boolean v ) | 写一个 boolean 当前输出流作为一个字节的值 |
void | writeByte( int v ) | 写了 byte 当前输出流作为一个字节的值 |
void | writeBytes( String s ) | 将字符串写入到基础的输出流作为字节序列 |
void | writeChar( int v ) | 写一个char当前输出流作为一个双字节的值,高字节优先 |
void | writeChars( String s ) | 将字符串写入底层输出流,作为一个字符序列 |
void | writeFloat( float v ) | 将浮点型参数的 int使用 floatToIntBits方法在类 Float,然后写道, int值基本为4字节输出流量,高字节优先。 |
void | writeDouble( double v ) | 将双参数到一个 long使用 doubleToLongBits方法在类 Double,然后写道, long值基本的输出流的字节的数量,高字节优先。 |
void | writeInt( int v ) | 写一个 int当前输出流为四个字节,高字节优先。 |
void | writeShort( int v ) | 写一个 short当前输出流的两个字节,高字节优先。 |
void | writeUTF( String str ) | 一个字符串写入到输出流的潜在使用在一个机器无关的方式 modified UTF-8编码。 |
案例 1:
package cn.pojo;
import
java.io.DataInputStream;
import
java.io.DataOutputStream;
import
java.io.File;
import
java.io.FileInputStream;
import
java.io.FileOutputStream;
//二进制流
public class
Demo2
{
public static void
main
(String[]
args
) {
// 1、指明目标和源
File
o
=
new
File("temp/Hello.class");
File
t
=
new
File(
"tmp/Hello.class"
);
// 2、构建流对象
DataInputStream
dis
=
null;
DataOutputStream
dos
=
null;
try
{
dis
=
new
DataInputStream(
new
FileInputStream(
o
));
dos
=
new
DataOutputStream(
new
FileOutputStream(
t
));
int
i;
// 3、读写流
while
((
i
=
dis
.read()) != -1) {
dos
.write(i);
}
dos
.flush();
System.
out
.println(
"操作成功!"
);
}
catch
(Exception
e
) {
e
.printStackTrace();
}
finally
{
// 4、关闭流
try
{
if
(
dos
!=
null
) {
dos
.close();
}
if
(
dis
!=
null
) {
dis
.close();
}
}
catch
(Exception
e
) {
e
.printStackTrace();
}
}
}
}
案例 2:
package cn.pojo;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo {
// 检查文件是否存在,否则创建
public static void checkFile(File file) {
if (!file.exists()) {
file.getParentFile().mkdirs();// 创建多级目录
try {
file.createNewFile();// 创建文件,此处需要处理异常
System.out.println("创建文件成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 明确源文件和目标文件
public static void main(String[] args) throws IOException {
myWrite();
myReader();
}
private static void myWrite() throws IOException {
// TODO Auto-generated method stub
// 创建数据输出流对象
File o = new File("E:/java48/111.txt");// 源文件
File t = new File("E:/java48/新建111.txt");// 目标文件
checkFile(o);
checkFile(t);
FileOutputStream fos = new FileOutputStream(o);
DataOutputStream dos = new DataOutputStream(fos);
// 写数据
dos.writeByte(10);
dos.writeShort(100);
dos.writeInt(1000);
dos.writeLong(10000);
dos.writeFloat(12.34F);
dos.writeDouble(12.56);
dos.writeChar('a');
dos.writeBoolean(true);
// 释放资源
dos.close();
}
private static void myReader() throws IOException {
// TODO Auto-generated method stub
// 创建数据输入流对象
File o = new File("E:/java48/111.txt");// 源文件
FileInputStream fis = new FileInputStream(o);
DataInputStream dis = new DataInputStream(fis);
// 读数据
byte b = dis.readByte();
short s = dis.readShort();
int i = dis.readInt();
long l = dis.readLong();
float f = dis.readFloat();
double d = dis.readDouble();
char c = dis.readChar();
boolean bl = dis.readBoolean();
// 释放资源
dis.close();
System.out.println(b);
System.out.println(s);
System.out.println(i);
System.out.println(l);
System.out.println(f);
System.out.println(d);
System.out.println(c);
System.out.println(bl);
}
}
输出内容为:
10
100
1000
10000
12.34
12.56
a
true
1.1.4 ObjectInputStream :对象输入流
特点 : 可以从输入流中读取java对象,而不需要每次读取一个字节,需要把InputStream包装到ObjectInputStream中,就可以从中读取对象,对象必须实现序列化,对象类实现Serializable接口
例:(实现序列化)
public
class
Pet
implements
Serializable {
private
static
final
long
serialVersionUID
= 1L;
}
构造方法:
1、ObjectInputStream( ) ;
2、ObjectInputStream( InputStream ins) ;
例如:创建方式 1 :
String path = "xx";// 路径和文件
File file = new File(path);// 创建文件
// 构建InputStream,然后ObjectInputStream
InputStream ins = null;
ObjectInputStream ois = null;
try {
ins = new FileInputStream(file);// 这里需要处理异常
ois = new ObjectInputStream(ins);// 两层构造
} catch (Exception e) {
e.printStackTrace();
}
创建方式2:
String path = "xx";// 路径和文件
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));// 多层构造,需要处理异常
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
常用方法:
返回值类型
|
方法名
|
方法简介
|
void | close( ) | 关闭输入流 |
int | read( ) | 读取一个字节的数据 |
int | read( byte [ ] b, int off, int len ) | 读入一个字节数组 |
boolean | readBoolean( ) | 在布尔值中读取 |
byte | readByte( ) | 读取一个8位字节 |
char | readChar( ) | 读取一个16位字符 |
double | readDouble( ) | |
float | readFloat( ) | |
int | readInt( ) | 读取一个32位的int |
String | readLine( ) | 过时的 |
Object | readObject( ) | 读取对象输入流中的对象 |
String | readUTF( ) | 读modified UTF-8的格式字符串 |
1.2.4 ObjectOutputStream :对象输出流
特点:
能够让你把对象写入到输出流中,而不需要每次写入一个字节。你可以把OutputStream包装到ObjectOutputStream中,然后就可以把对象写入到该输出流中了
对象必须实现序列化,对象类
实现Serializable接口
例:(实现序列化)
public
class
Pet
implements
Serializable {
private
static
final
long
serialVersionUID
= 1L;
}
构造方法:
1、ObjectOutputStream( ) ;
2、ObjectOutputStream( OutputStream ins) ;
例如:创建方式 1 :
String path = "xx";// 路径和文件
File file = new File(path);// 创建文件
// 构建OutputStream,然后ObjectOutputStream
OutputStream outs = null;
ObjectOutputStream oos = null;
try {
outs = new FileOutputStream(file);// 这里需要处理异常
oos = new ObjectOutputStream(outs);// 两层构造:先用FileOutputSTream,再用ObjectOutputStream
} catch (Exception e) {
e.printStackTrace();
}
创建
方式
2:
String path = "xx";// 路径和文件
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));// 多层构造,需要处理异常
} catch (Exception e) {
e.printStackTrace();
}
常用方法:
返回值类型
|
方法名
|
方法简介
|
void | close( ) | 关闭流 |
void | flush( ) | 刷新流 |
protect Object | replaceObject( ) | 这种方法将允许受信任的子类对象来代替一个物体对另一个序列化期间 |
void | write( byte [ ] b ) | 写入一个字节数组 |
void | write( byte [ ] b, int off, int len ) | 写入字节数组的字节数 |
void | write( int val ) | 写一个字节 |
void | writeBoolean( boolean val ) | 写一个布尔值 |
void | writeByte( byte val ) | 写入一个8位字节 |
void | writeChar( int val ) | 写入一个16位字符 |
void | writeInt( int val ) | 写入一个32位长的int |
void | writeObject( Object obj ) | 写入指定对象的对象 |
void | writeUTF( String str ) | 原始数据写在 modified UTF-8格式字符串 |
ObjiectInputStream 和 ObjectOutputStream 案例:(创建一个宠物类,放入一个集合中,使用者两个类进行读写操作)
package cn.pojo;
import java.io.Serializable;
//宠物类
public class Pet implements Serializable {
// 要实现序列化
private static final long serialVersionUID = 514910705505845579L;
private String id;// id编号
private String name;// 昵称
public Pet() {
}
public Pet(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Pet [id=" + id + ", name=" + name + "]";
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
public class Demo3_Pet {
public static void main(String[] args) {
// 1、明确当前目标和源
File o = new File("F:/temp/pet.txt");
File t = new File("F:/temp/pet.txt");
ArrayList<Pet> arr = new ArrayList<Pet>();
Pet pet1 = new Pet("001", "小白");
Pet pet2 = new Pet("002", "小绿");
Pet pet3 = new Pet("003", "大黄");
arr.add(pet1);
arr.add(pet2);
arr.add(pet3);
// 2、构建流对象
InputStream ins = null;
OutputStream outs = null;
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
try {
outs = new FileOutputStream(o);
oos = new ObjectOutputStream(outs);
// 输出对象信息:序列化
oos.writeObject(arr);
oos.flush();
System.out.println("写出成功!");
// 读文件对象:反序列化
ins = new FileInputStream(o);
ois = new ObjectInputStream(ins);
Object ob = ois.readObject();
// 遍历输出集合中对象信息
if (ob instanceof ArrayList) {
@SuppressWarnings("unchecked")
ArrayList<Pet> li = (ArrayList<Pet>) ob;
for (Pet p : li) {
System.out.println(p);
}
}