比较好的文章:添加链接描述
一、IO
IO流是:java程序和文件交互的过程
IO流就是使用java技术将文件中的内容读取到java程序中,或者将程序中的内容保存到java文件中的过程
IO流的大致分类:
- IO流的方向:输入流,输出流
- 数据流量大小:字节流,字符流
- 按功能:节点流,处理流
1、1字节流
java中所有的IO流的底层全部都是字节流
1、1、1字节输入流InputStream
使用已知实现子类:FileInputStream
基本步骤如下:
- 指定要操作的文件
- 将文件读取到IO流
- 从IO流中获取内容保存到java程序中
- 关闭资源,先开的后关,后开的先关
读取数据的两种方法: - 读取数据到数组中
// 读取信息
@Test
void inputio1() {
// 指定文件
File file = new File("demo.txt");
try {
// 将文件读取到io流中
InputStream in = new FileInputStream(file);
// 获取文件内容的大小
System.out.println("文件内容的长度是" + in.available());
/*
* 从io流中获取内容保存到java程序中 在程序中使用自己的数组来保存,数组的长度必须能够放得下文件内容
*/
byte[] bytes = new byte[in.available()];
in.read(bytes);
// 显示信息
String str = new String(bytes);
// 关闭资源
in.close();
System.out.println(str);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
- 一个一个读取字节
// 读取信息,一个一个的读取字符
@Test
void inputio2(){
//确定要读取的文件位置,程序启动的时候会默认去项目的根目录下找文件
File file = new File("demo.txt");
try {
//创建输入流,将文件读取到io流中
InputStream in = new FileInputStream(file);
//一个一个读取,得到每一个字符的unicode编码,如果读到最后一个字符之后,返回-1
int c = -1;
while((c = in.read()) != -1) {
System.out.println((char)c);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、1、2、字节输出流OutputStream
基本步骤:
- 要写出的文件内容
- 指定要写出的目标文件
- 写出去
- 刷新
- 关闭资源
注意事项: - java程序在往出写的时候,一定要进行先flush再进行刷新
- 每一次给文件中写数据,是追加到原有内容之后还是覆盖原有内容。
// 写出信息
@Test
void outputio() {
// 指定要写出的内容
String mess = "抱着沙发,睡眼昏花,凌乱头发。却渴望像电影主角一样潇洒";
/*
* 要写出去的目标文件如果存在的话,会直接写出,如果不存在的话,便会自动创建文件,但只会自动创建文件,
* 不会自动创建目录,因此我们要首先判断一下看路径是否存在,如果路径不存在的话,先创建目录
*/
File outfile = new File("file\\demo.txt");
File parentFile = outfile.getParentFile();
parentFile.mkdirs();
// 往出写,将数据保存到byte数组中
byte[] bytes = mess.getBytes();
try {
// 创建输出流
OutputStream out = new FileOutputStream(outfile);
out.write(bytes);
// 关闭资源
// 刷新,将io流中的信息,刷新到文件中
out.flush();
out.close();
System.out.println("保存成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、2使用字节流实现文件的拷贝
先读取,然后再写出去
写文件的方式
- 一边读取一边写,一个字节一个字节的处理
- 使用数组缓冲区的方式
@Test
void copy01() {
// 指定源文件的位置
File sfile = new File("E:\\demo.txt");
// 指定目标文件的位置
File dfile = new File("E:\\newdemo.txt");
//创建读取流,写出流
try {
FileInputStream fis = new FileInputStream(sfile);
FileOutputStream fos = new FileOutputStream(dfile);
//一个字节一个字节的读取,
int bt = 0;
//循环读取,写出
while((bt = fis.read()) != -1) {
//写出去
fos.write(bt);
}
//关闭资源
fos.flush();
fos.close();
fis.close();
System.out.println("文件拷贝成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Test
void copy01() {
//指定源文件的位置
File sfile = new File("E:\\demo.txt");
//指定目标文件的位置
File dfile = new File("E:\\newdemo.txt");
try {
//创建读取流,写出流
FileInputStream fis = new FileInputStream(sfile);
FileOutputStream fos = new FileOutputStream(dfile);
//创建数组容器
byte [] bytes = new byte[fis.available()];
//使用输入流,将源文件保存到数组中
fis.read(bytes);
//将数组中的内容,写出到目标文件中
fos.write(bytes);
//关闭资源
fos.flush();
fos.close();
fis.close();
System.out.println("文件拷贝成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、3字符流
每一次操作最小单位是一个字符,字符流只能用来进行文本文件的操作。
1、3、1Reader FileReader
//从文件中读取数据,字符输入流
@Test
void charin(){
//源文件
File file = new File("demo.txt");
//输入流
try {
Reader reader = new FileReader(file);
// //读取到一个char数组中,也可以单个去读取
// char [] ch = new char[10];
// reader.read(ch);
// String str = new String(ch);
// System.out.println(str);
//一个一个的读取
int c = 0;
while((c = reader.read()) != -1) {
System.out.print((char)c);
}
//关闭资源
reader.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、3、2Writer FileWriter
//向文件中写数据
@Test
void charout(){
//写出目标
File file = new File("demo.txt");
//写出内容
String mess = "我是中国人";
//输出流 FileWriter
try {
Writer w = new FileWriter(file,true);
//输出
w.write(mess);
//关闭资源
//强制刷新,但是不会关闭流
w.flush();
//要关闭,对数据进行刷新操作
w.close();
//注意:在关闭流之后无法进行数据的刷新操作
System.out.println("写出成功");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、4转换流
1、4、1字符输出转换流(OutputStreamWriter)
步骤:
- 创建字节输出流
- 创建转换流将字节流包进去
- 使用转换流进行输出
//输出,字符转字节
@Test
void chartobyte(){
//目标文件
File file = new File("out.txt");
try {
//创建字节输出流
FileOutputStream fos = new FileOutputStream(new File("out.txt"),true);
//创建转换流,将字节流包进去,设置转换时使用的编码格式
/*
* 参数一:转换的字节输出流
* 参数二:转换后使用的编码
*/
OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
//使用转换流进行输出
osw.write("这是转换流的操作");
//关闭资源
osw.flush();
osw.close();
fos.close();
System.out.println("写出成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、4、2字符输入转换流(InputStreamReader)
步骤:
- 创建字节输入流
- 创建转换流将字节流包进去
- 使用转换流进行输入
//输入,读取操作
@Test
void bytetochar(){
//将字节输入流交给字符输出流
try {
FileInputStream fis = new FileInputStream(new File("out.txt"));
//使用文件编码读取到内存中,字节内容转换为字符
InputStreamReader isr = new InputStreamReader(fis,"GBK");
System.out.println("获取当前所用的编码为"+isr.getEncoding());
int c = -1;
while((c = isr.read()) != -1) {
System.out.print((char)c);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、5缓冲流
- 缓冲流的主要作用是提高读写速度,
- 缓冲流的默认缓冲区大小是8kb,是8192个字节
1、5、1字节缓冲流
BufferedOutputStream;
//字节输出缓冲流
@Test
void byteout(){
try {
//创建字节输出流
FileOutputStream fos = new FileOutputStream(new File("buffer.txt"));
//字节输出缓冲流
BufferedOutputStream bos = new BufferedOutputStream(fos);
//使用缓冲流写
bos.write("你好缓冲流".getBytes());
//关闭资源
bos.flush();
bos.close();
fos.close();
System.out.println("写出成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
BufferedInputStream;
//字节输入缓冲流
@Test
void bytein(){
try {
FileInputStream fis = new FileInputStream(new File("buffer.txt"));
//字节输入缓冲流
BufferedInputStream bis = new BufferedInputStream(fis);
byte [] bytes = new byte[bis.available()];
bis.read(bytes);
System.out.println(new String(bytes));
bis.close();
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、5、2字符缓冲流
BufferedWriter;
//数据的写入
@Test
void write() {
File file = new File("buffer.txt");
//创建字符写出流
try {
Writer w = new FileWriter(file);
//使用缓冲流进行写入
BufferedWriter bw = new BufferedWriter(w);
//要写入的数据
String mess = "我是字符缓冲流";
//数据的写入
bw.write(mess);
//刷新
bw.flush();
bw.close();
w.close();
System.out.println("数据写入成功");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
BufferedReader;
@Test
void read(){
File file = new File("buffer.txt");
//创建字符输出流
try {
Reader rd = new FileReader(file);
//使用缓冲流进行读取
BufferedReader br = new BufferedReader(rd);
//一个一个的读取
int c=0;
while((c = br.read()) != -1) {
System.out.println((char)c);
}
//关闭流
br.close();
rd.close();
System.out.println("数据读取成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、6Properties
- 该类的特点:键值对集合,键值对的类型都是String类型的
- 基本步骤:
确定目标文件、源文件和要写出去的文件的位置file
创建输入输出流:字节,字符,转换,缓冲
读取内容或者写出内容
关闭资源(强制刷新)
//properties读取文件
@Test
void proper02() {
//源文件
File file = new File("db.properties");
//io流,使用字节流
try {
FileInputStream fis = new FileInputStream(file);
//创建容器 properties
Properties pt = new Properties();
//读取io流管道中的内容
pt.load(fis);
//关闭资源
fis.close();
System.out.println(pt);
System.out.println("用户名"+pt.getProperty("username"));
System.out.println("密码"+pt.getProperty("password"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//将内容写出到properties配置文件中
@Test
void proper03(){
//目标文件
File file = new File("db.properties");
//创建properties容器,写入数据
Properties pt = new Properties();
pt.setProperty("password", "abcdef");
pt.setProperty("username", "zhangsan");
//创建字节输出流
try {
FileOutputStream fos = new FileOutputStream(file);
//写出去
pt.store(fos, "这是我自己写出去的配置信息");
//关闭资源
fos.close();
System.out.println("写出成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、7序列化流
- 序列化:将java对象(自定义对象)以字节序列的形式保存
- 反序列化:将字节序列的内容读取为java对象
- 要序列化的对象必须实现Serializable接口
- 要想反序列化,首先得进行序列化
1、7、1ObjectOutputSteam
- 在序列化对象的时候,对象必须实现Serializable接口
- 对象属性如何不被序列化:使用static,transient修饰的属性不会被序列化
- 如何确定对象是同一个:该类的序列版本号与从流中读取的类描述符的版本号匹配的时候。
// 序列化
@Test
void write() {
// 目标对象
File file = new File("stu.txt");
// 字节输出流
try {
FileOutputStream fos = new FileOutputStream(file);
// 创建序列化流
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 创建对象
Student stu = new Student("张三", 20);
Student stu01 = new Student("李四", 30);
ArrayList<Student> stus = new ArrayList<Student>();
stus.add(stu);
stus.add(stu01);
// 写出去
oos.writeObject(stus);
oos.flush();
oos.close();
fos.close();
System.out.println("序列化成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、7、2ObjectInputStream
// 反序列化
@Test
void read() {
//源文件
File file = new File("stu.txt");
//创建字节输入流
try {
FileInputStream fis = new FileInputStream(file);
//创建反序列化流
ObjectInputStream ois = new ObjectInputStream(fis);
//读取对象信息
ArrayList<Student> stus=(ArrayList<Student>)ois.readObject();
//关闭资源
ois.close();
fis.close();
System.out.println(stus);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、8标准打印输出流
- 使用标准输出流可以直接将信息写出到文件中去,也可以向文件中写入任意类型的数据。
1、8、1字节输出流(PrintStream)
// 字节标准打印输出流
@Test
void byteprint2() {
// 目标文件
File file = new File("print.txt");
// 创建输出流
try {
FileOutputStream fos = new FileOutputStream(file);
// 创建输出流
PrintStream ps = new PrintStream(fos);
ps.write("字节打印输出流".getBytes());
ps.flush();
ps.close();
fos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、8、2字符输出流(PrintWriter)
// 字符标准打印输出流
@Test
void charprint(){
//目标文件
File file = new File("print.txt");
//输出流
try {
FileOutputStream fos = new FileOutputStream(file);
PrintWriter pw = new PrintWriter(fos,true);
/**
* println,printf或者format方法将刷新输出缓冲区
*/
//写出内容
pw.println(10.5);
//关闭资源
pw.flush();
pw.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
注意事项:
- 在使用标准打印输出流的时候,可以创建自带刷新缓冲区功能,也可以不带自动刷新。但我们无论使用什么样的输出流:先手动刷新然后再关闭。
- 使用print、println、write写出数据
- 可以将任意类型的数据直接写出到文件中
1、9java的其他流
1、9、1数组流(ByteArrayInputStream)
1、9、2字符串流
- 快速将字符串写出到文件中,设定一个缓冲区,提高写出速度
1、9、3数据流
- 可以将基本数据类型写出去
代码演示如下:
//数据流
@Test
void dataOutio() {
//创建写出流
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("data.txt")));
//写出数据
dos.writeDouble(100.0);
dos.writeBoolean(true);
dos.writeByte(10);
//刷新关闭
dos.flush();
dos.close();
System.out.println("写出成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//数据流
@Test
void dataInio(){
try {
DataInputStream dis = new DataInputStream(new FileInputStream(new File("data.txt")));
double readDouble = dis.readDouble();
System.out.println(readDouble);
boolean readBoolean = dis.readBoolean();
System.out.println(readBoolean);
byte readByte = dis.readByte();
System.out.println(readByte);
dis.close();
System.out.println("读取成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}