一、IO
1.1 简介:
1.I==>Input 输入 Output 输出 用于不通过设备进行信息的交互
2.使用的场景:
A.文件的复制
B.文件上传的下载
C.(即时通信)微信中信息的传递
3.IO 分类
流向划分:输入流与输出流
类型划分:字节流与字符流
4.输入流与输出流的解释
5.字节流与字符流的解释
字节流:
A.万物皆字节 系统上任何的资源都可以使用字节来进行表示
B.一般读写文件 音视频 图片
C.分类:字节输入流(读) 字节输出流(写)
字符流:
A.字符流=字节流+编码表 字符流的底层也是使用字节流来进行操作的 只能底层通过编码表将字节转换为字符
B.读取纯字符的文件
C.分类:字符输入流(读) 与字符输出流(写)
6.IO操作的注意点:
A.所有的流的资源都是java.io包下
B.使用流资源的时候 可能会产生异常 需要对异常处理(捕获 抛出)
C.所有的流资源使用之后 必须进行关闭 因为流资源比较消耗内存
1.2 OutputStream
1.2.1 简介
此抽象类是表示输出字节流的所有类的超类
1.2.2 常用的方法
方法的名称 | 方法的描述 |
---|---|
public abstract void write(int b) | 一个一个字节写入 |
public void write(byte[] b) | 将字节数组的内容写入 |
public void write(byte[] b, int off, int len) | 将字节数组的指定的长度的内容写入 |
public void flush() | 将缓冲区的数据刷新到硬盘中 |
public void close() | 关闭流资源 |
1.3 FileOutputStream
1.3.1 简介
- 文件字节输出流是用于将数据写入 File 将数据写入到文件中
- FileOutputStream 用于写入诸如图像数据之类的原始字节的流
- 要写入字符流,请考虑使用 FileWriter
1.3.2 使用步骤
A例化FileOutputStream
B.调用写的方法
C.关闭资源
1.3.3 使用字节流写字符串到文件中
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Test01 {
public static void main(String[] args) throws IOException {
//实例化FileOutputStream
OutputStream os =new FileOutputStream("d:\\a\\4.txt",true);//true末尾追加
String s="阿豪牛牛牛";
//将字符串转换为字节数组
byte[] b = s.getBytes();
os.write(b);
os.close();
}
}
1.3.4 说明
问题: 写入的字节是 97 98 99 使用记事本打开就是 a b c
原因: 记事本打开的文件的时候 如果字节的范围是 0-127 使用ASCII表来识别
超出范围 使用的记事本默认的码表来识别 默认的码表就是GBK
1.4 InputStream
1.4.1 简介
- 此抽象类是表示字节输入流的所有类的超类
- InputStream 是一个抽象类
- InputStream是输入流的所有类的超类
1.4.2 常用的方法
方法 的名称 | 方法的描述 |
---|---|
public void close() | 关闭资源 |
public abstract int read() | 一个一个字节读取 |
public int read(byte[] b) | 将读取的内容存入到缓冲数组中 |
public int read(byte[] b, int off, int len) | 读取指定长度的内容存入缓冲数组中 |
1.5 FileInputStream
1.5.1简介
- FileInputStream 用于来读取文件中的内容
- FileInputStream 用于读取诸如图像数据之类的原始字节流 用于操作字节
- 要读取字符流,请考虑使用 FileReader
1.5.2 使用步骤
A.实例化FileInputStream
B.调用读取的方法
C.关闭流资源
1.5.3 一次读取多个字节
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test02 {
public static void main(String[] args) throws IOException {
InputStream is = new FileInputStream("d:\\a\\1.txt");
//定义缓存区的数组
byte [] b = new byte[1024];
int length=-1;
while ((length=is.read(b)) !=-1){
System.out.println(new String(b,0,length));
}
//关闭资源
is.close();
}
}
1.5.4 read() 与 read(b)比较
A.read() 一个一个字节读 效率低 read(b) 一次读取多个字节放入到数组 效率高
B.read() 返回值是读取的字节 read(b) 返回值是读取的有效的字节的个数
1.6 文件复制
代码:
import java.io.*;
public class Test05 {
public static void main(String[] args) throws IOException {
//实例化输入流
InputStream is = new FileInputStream("d:\\a\\1.jpg");
//实例化输出流
OutputStream os = new FileOutputStream("c:\\admin\\1.jpg");
byte [] b = new byte[1024];
int length =-1;
while ((length =is.read(b)) !=-1) {
os.write(b,0,length);
}
//关闭资源
os.close();
is.close();
}
}
1.7 高效流
1.7.1 读写视频案例
import java.io.*;
public class Test01 {
public static void main(String[] args) {
OutputStream os = null;
BufferedOutputStream bos = null;
InputStream is = null;
BufferedInputStream bis = null;
try {
os = new FileOutputStream("d:\\a\\1.mp4");
bos =new BufferedOutputStream(os);
is =new FileInputStream("E:\\IO\\a.mp4");
bis =new BufferedInputStream(is);
int length = -1;
while ((length = bis.read()) != -1) {
bos.write(length);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (bos !=null){
bos.close();
}
if (bis !=null){
bis.close();
}
if (is !=null ){
is.close();
}
if (os !=null){
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
1.8 关闭资源
- 从下往上进行关闭(最后的使用先关闭)
- 不管是否发生异常 都会要关闭io流资源 在finally中关闭流资源
- 关闭流资源 需要进行非空验证
二、字符流
2.1 简介
1.字符流:用于读写字符
2.分类:字符输入流(读) 字符输出流(写)
3.使用字符流原因:
使用字节流读取字符 需要将读取的内容来进行转换,转换错误可能会出现乱码 使用字节操作字符比较麻烦
字符流=字节流+编码表
4.任何的编码表下 中文的第一个字节都是负数 根据这个规律来进行转换
2.2 字符流-写Witer
- Writer 写入字符流的抽象类
- 子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。
- 多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能
2.3 FileWriter
2.3.1 简介
-
用来写入字符文件的便捷类
-
可以先在 FileOutputStream 上构造一个 OutputStreamWriter 设置编码表格式
-
FileWriter 用于写入字符流。要写入原始字节流,请考虑使用 FileOutputStream。
2.3.2 构造方法
方法的名称 | 方法的描述 |
---|---|
public FileWriter(File file) | 根据给定的 File 对象构造一个 FileWriter 对象 |
public FileWriter(File file, boolean append) | 根据给定的 File 对象构造一个 FileWriter 对象。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处 |
public FileWriter(String fileName) | 根据给定的文件名构造一个 FileWriter 对象 |
public FileWriter(String fileName, boolean append) | 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象 |
代码—写:
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Test01 {
public static void main(String[] args) throws IOException {
Writer w = new FileWriter("1.txt");
w.write(97);
w.write(new char[]{'b','c'});
w.write("今天天气真好!适合学习java");
w.close();
}
}
3.4 字符流-读 Reader
3.4.1 简介
- 用于读取字符流的抽象类
- 子类必须实现的方法只有 read(char[], int, int)
- 多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能
3.4.2 字符流-读
代码:
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class Test02 {
public static void main(String[] args) throws IOException {
Reader r = new FileReader("1.txt");
char [] ch = new char[1024];
int length=-1;
while ((length =r.read(ch)) !=-1) {
System.out.println(new String(ch,0,length));
}
//关闭资源
r.close();
}
}
3.5 注意点
A.不能使用字符流来读取音视频以及图片
B. 原因:因为使用字符流读取文件的时候 需要依赖于编码表来进行转换
音视频 不能使用常规编码表来进行转换
三、 转换流
3.1 InputStreamReader-简介
- InputStreamReader 是字节流通向字符流的桥梁
- 它使用指定的 charset 读取字节并将其解码为字符 可以设置其编码的格式
- 为了达到最高效率,可要考虑在 BufferedReader
3.2 InputStreamReader 读
import java.io.*;
public class Test01 {
public static void main(String[] args) throws IOException {
InputStream is = new FileInputStream("1.txt");
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
int leng =-1;
//byte [] b = new byte[1024];
while ((leng =isr.read()) !=-1){
System.out.println((char) leng);
}
}
}
3.3 OutputStreamWriter-简介
- OutputStreamWriter 是字符流通向字节流的桥梁
- 使用指定的 charset 将要写入流中的字符编码成字节 可以设置其编码表
- 为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中
3.4 OutputStreamWriter 写
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class Test02 {
public static void main(String[] args) throws IOException {
OutputStream os = new FileOutputStream("3.txt");
OutputStreamWriter osw = new OutputStreamWriter(os,"GBK");
osw.write("哈哈哈今天又到星期一");
osw.close();
os.close();
}
}
四、字符的高效流
4.1 高效流-读-BufferedReader 简介
- 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取
- 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了
4.2 BufferedReader-读
import java.io.*;
public class Test01 {
public static void main(String[] args) throws IOException {
// Reader r = new FileReader("1.txt");
/* InputStream is = new FileInputStream("1.txt");
InputStreamReader in = new InputStreamReader(is,"Utf-8");
BufferedReader br = new BufferedReader(in);*/
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("1.txt"),"UTF-8"));
String line=null;
while ((line = br.readLine()) !=null){
System.out.println(line);
}
br.close();
// in.close();
// is.close();
}
}
4.3 高效流-写 BufferedWriter简介
- 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写
- 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入
- 该类提供了 newLine() 方法 表示换行
4.4 BufferedWriter-写
import java.io.*;
public class Test02 {
public static void main(String[] args) throws IOException {
/* Writer w = new FileWriter("4.txt");
BufferedWriter bw = new BufferedWriter(w);*/
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("6.txt"),"UTF-8"));
bw.write("詹姆斯完爆勇士");
bw.newLine();
bw.write("蓝网阿杜回顾");
//刷新的方法
// bw.flush();
bw.close();
// w.close();
}
}
4.5 close() 与flush()的比较
- flush() 将缓冲区的数据刷新到硬盘中
- close() 关闭流资源
close() 方法的底层会调用flush()方法 - 区别:
调用 close() 方法之后 流资源就不能使用
调用 flush() 方法之后 流资源是可以使用
五、对象流
5.1 序列化与反序列化
1.使用场景:将读写存储的文件的时候 或者是在网络通信传输对象的时候 就需要使用序列化(读写文件中的对象)
要被序列化的对象,类需要实现Serializable接口
2.序列化机制:使用一个序列化的字节(唯一的标识) 来表示文件中的对象(属性值 以及方法)
3.序列化:将对象写入到文件中的过程 就是序列化 将对象进行流化 加快对象写入到文件的速度
4.反序列化:将文件的序列化的对象 读取的过程 就是反序列化 加快读取的速度
5.2 案例
import java.io.Serializable;
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
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 "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//序列化
OutputStream os = new FileOutputStream("src\\4.txt");
ObjectOutputStream oos = new ObjectOutputStream(os);
ArrayList<Student> list = new ArrayList<>();
// oos.writeObject(new Student("张三",18));
// oos.writeObject(new Student("李四",19));
Student stu1 = new Student("张三", 18);
Student stu2 = new Student("李四", 19);
Student stu3 = new Student("王五", 20);
list.add(stu1);
list.add(stu2);
list.add(stu3);
oos.writeObject(list);
oos.flush();
oos.close();
os.close();
//反序列化
FileInputStream fis = new FileInputStream("src\\4.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
List<Student> list1 = (ArrayList) ois.readObject();
list1.forEach(student -> System.out.println(student));
}
}