一、什么是IO流
流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出。
使用流有两个操作:
-
向流中添加数据
写
-
从流中取得数据
读
二、IO流的分类
1、按照流向分
-
输入流
读入内存中
-
输出流
流出内存写出的流
2、按照操作数据的最小的单位
-
字节流
每个字节每个字节的读,每个字节每个字节的写
每读写一次都是一个字节
-
字符流
每读写一次都是一个字符
3、按照功能分
-
节点流
直接跟输入输出源对接
-
处理流
建立在低级流的基础上,对接的是节点流
处理流的目的是更加方便,高效的进行数据读写操作
三、常用的IO流
字节操作相关的流
InputStream(输入流、字节流)
- FileInputStream(文件输入字节流 - 节点流)
- BufferedInputStream(缓冲流 )
- ObjectInputStream(对象输入字节流 - 处理流)
- ByteArrayInputStream(字节数组输入流[内存流] - 用它来缓存数据)
- DataInputStream(读取Java基本类型的数据)
OutputStream(输出流、字节流)
- FileOutputStream
- BufferedOutputStream
- ObjectOutputStream
- ByteArrayOutputStream
- DataOutputStream
字符操作相关的流
Reader(输入流、字符流)
- FileReader(文件输入字符流)
- BufferedReader(缓冲流 - 缓冲的是字符)
- InputStreamReader(字符流 - 转换流 - 将字符流转为字节流)
Writer(输出流、字符流)
- FileWriter
- BufferedWriter
- OutputStreamWriter(字符输出流- 转换流 - 将字符输出流转为字节输出流)
1、文件操作
(1)读取文件内容(文本文件)
-
选流
-
输入流
-
字节流/字符流
InputStream/Reader
-
操作文件的
FileInputStream/FileReader
-
-
文件字节输入流
未关流:
public class FileInputStreamTest {
public static void main(String[] args) {
InputStream in = null;
try {
//1、创建输入流对象
// InputStream in = new FileInputStream("D:/bbb/test.txt");
in = new FileInputStream(new File("D:/bbb/test.txt"));
//2、调用方法读取
//如果我们想读取文件所有的内容,肯定要使用循环,结束循环的条件是最后读到的值为-1
int i;
while((i = in.read()) != -1) {
System.out.println(i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//3、关闭流
try {
if(in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
我们使用字节流读文本文件,如果文本文件出现中文等特殊字符,会导致读取乱码
读取文件内容,我们建议使用字符流,字符是一个字符一个字符的读
-
文件字符输入流
public class FileReaderTest { public static void main(String[] args) { Reader reader = null; try { //1、创建流对象 reader = new FileReader("D:/bbb/test.txt"); //2、循环读 int i; while((i = reader.read()) != -1) { System.out.println((char)i); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { //3、关闭流 try { if(reader != null) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
-
字符流 - 一行一行的读
BufferedReader
package com.qjzx._06_bufferedreader; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.List; public class BufferedReaderTest { public static void main(String[] args) { List<Student> list = new ArrayList<>(); try( Reader reader = new FileReader("F:\\课程资料\\2021-06-15-IO\\doc\\练习.txt"); BufferedReader br = new BufferedReader(reader); ){ //行数据 String line; br.readLine();//先读一行 while((line = br.readLine()) != null) { //line = "1,张三,18,男"; String[] split = line.split(",");//["1","张三","18","男"] Student st = new Student(Integer.parseInt(split[0]),split[1],Integer.parseInt(split[2]),split[3]); list.add(st); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println(list); } } class Student{ private int id; private String name; private int age; private String gender; public Student() {} public Student(int id, String name, int age, String gender) { super(); this.id = id; this.name = name; this.age = age; this.gender = gender; } public int getId() { return id; } public void setId(int id) { this.id = id; } 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; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + "]"; } }
(2)数据写入文件
-
字节操作
package com.qjzx._03_fileoutputstream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; /** * * 1、创建FileOutputStream对象 * FileOutputStream(File file) * 覆盖 * FileOutputStream(File file, boolean append) * true 追加内容 false 覆盖内容(先清空之前的内容) * FileOutputStream(String name) * FileOutputStream(String name, boolean append) * 2、调用方法进行写操作 * 3、关闭流 * * @author Administrator * */ public class FileOutputStreamTest { public static void main(String[] args) { /** * try后面的()中可以创建流的对象 * 流在使用结束后自动关闭 * 前提是流实现Closeable接口 */ try (OutputStream out = new FileOutputStream("D:/bbb/test.txt",true)){ out.write('D'); out.write('D'); out.write('D'); out.write('D'); out.write('D'); out.write('我'); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
-
字符操作
public class FileWriterTest { public static void main(String[] args) { try(FileWriter writer = new FileWriter("D:/bbb/test.txt",true)){ writer.write('我'); writer.write('是'); writer.write('中'); writer.write('国'); writer.write('人'); writer.write("我爱中国"); } catch (IOException e) { e.printStackTrace(); } } }
-
一行一行的写
BufferedWriter
newLine() 跨平台换行
public class BufferedWriterTest { public static void main(String[] args) { //准备数据 /* List<Student> list = new ArrayList<>(); list.add(new Student(4,"赵六",21,"男")); list.add(new Student(5,"田七",25,"女")); */ List<Student> list = Arrays.asList( new Student(4,"赵六",21,"男"), new Student(5,"田七",25,"女")); try( Writer writer = new FileWriter("F:\\课程资料\\2021-06-15-IO\\doc\\练习.txt",true); BufferedWriter bw = new BufferedWriter(writer); ){ //先换个行 bw.newLine(); //写 for (Student student : list) { bw.write(student.toString()); //写完之后换行 bw.newLine(); } } catch (IOException e) { e.printStackTrace(); } } }
(3)文件的复制
/**
* 如何提高效率?
* read(byte[] bytes)这个方法
* 一次读多个字节
* @author Administrator
*
*/
public class FileCopyPlus {
public static void main(String[] args) {
try(
InputStream in = new FileInputStream("F:\\课程资料\\2021-05-24-Java概述与环境搭建\\video\\01_计划安排.mp4");
OutputStream out = new FileOutputStream("D:/abc.mp4");
){
byte[] buffer = new byte[1024];
int length;
//读
while((length = in.read(buffer)) != -1) {
//写,buffer缓冲的字节数组,0 从buffer的那个位置开始写,length 写几个(读几个就写几个)
out.write(buffer,0,length);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(4)文件的剪切
- 先复制,再删除
2、对象操作
ObjectInputStream 反序列化
ObjectOutputStream 序列化
可以序列化的对象必须实现 Serializable接口
- 对象的持久化
public class ObjectDurableTest {
public static void main(String[] args) {
Student st = new Student(1,"张三",19,"女");
try(
OutputStream out = new FileOutputStream("d:/student.obj");
ObjectOutputStream objOut = new ObjectOutputStream(out);
){
//将java对象写入到流中保存到其他地方,序列化
//可以被序列化的对象必须实现Serializable接口
objOut.writeObject(st);//java.io.NotSerializableException
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 对象的反序列化
public class ObjectInputStreamTest {
public static void main(String[] args) {
try(
InputStream in = new FileInputStream("d:/student.obj");
ObjectInputStream objIn = new ObjectInputStream(in);
){
Object object = objIn.readObject();
//反序列化,通过流读取数据加载到内存中,创建java对象
Student st = (Student) object;//创建了一个对象
System.out.println(st);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
- 集合的序列化与反序列化
public class ListSeralizableTest {
public static void main(String[] args) {
/*
* 序列化
List<Student> list = Arrays.asList(
new Student(4,"赵六",21,"男"),
new Student(5,"田七",25,"女"));
try(
OutputStream out = new FileOutputStream("d:/students.obj");
ObjectOutputStream objOut = new ObjectOutputStream(out);
){
objOut.writeObject(list);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
*/
try(
InputStream in = new FileInputStream("d:/students.obj");
ObjectInputStream objIn = new ObjectInputStream(in);
){
Object object = objIn.readObject();
List<Student> list = (List<Student>) object;//创建了一个对象
System.out.println(list);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
四、流的选择
文件内容操作的时候
FileInputStream/FileOutputStream
FileReader/FileWriter
ObjectInputStream/ObjectOutputStream
BufferedReader/BufferedRWriter
File…操作文件
Object…操作对象
Buffered…缓冲
如果我们只是简单的读写
InputStream/OutputStream
Reader/Writer
流向的判断:内存!!!!
- 先判断流向
- 选择操作的单位
- 数据源
- 处理 - 处理流
= (List) object;//创建了一个对象
System.out.println(list);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
# 四、流的选择
文件内容操作的时候
FileInputStream/FileOutputStream
FileReader/FileWriter
ObjectInputStream/ObjectOutputStream
BufferedReader/BufferedRWriter
File.....操作文件
Object....操作对象
Buffered....缓冲
如果我们只是简单的读写
InputStream/OutputStream
Reader/Writer
流向的判断:内存!!!!
- 先判断流向
- 选择操作的单位
- 数据源
- 处理 - 处理流