1 IO介绍以及分类
IO: Input Output
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作
1.1 IO流的分类
1. 根据处理的数据类型不同可以分为:字符流和字节流。
2. 根据数据的流向不同可以分为:输入流和输出流。
1.2 字节流(Byte Stream)
1.字节流以字节为单位进行读取和写入操作,适合处理二进制数据(如图片、视频、音频等)或者文本文件。
2.字节流类通常以 InputStream 和 OutputStream 结尾,例如 FileInputStream、FileOutputStream。
3.字节流可以用于读写任何类型的文件,但对于文本文件的处理可能需要做字符编码转换。
1.3 字符流(Character Stream)
1.字符流以字符为单位进行读取和写入操作,适合处理文本数据。字符流会自动处理字符编码转换,避免了字节流在处理文本时可能出现的乱码问题。
2.字符流类通常以 Reader 和 Writer 结尾,例如 FileReader、FileWriter。
3.字符流适合处理文本文件,能够更方便地读写文本中的字符数据。
1.4 选择建议
1.如果你需要处理文本文件,推荐使用字符流,因为它们能够更好地处理字符编码和文本数据。
2.如果需要处理二进制文件或者未经处理的数据,应该使用字节流。
2 字符流
@Test
public void test1() {
FileReader fileReader = null;//声明放在外边 局部变量必须初始化
//FileReader fileReader;//声明放在外边 ×××××
try {
fileReader = new FileReader("io.txt");//打开水龙头
//Reads a single character.
int ch1 = fileReader.read();
System.out.println((char)ch1);//a
int ch2 = fileReader.read();
System.out.println((char)ch2);//b
int ch3 = fileReader.read();
System.out.println((char)ch3);//c
int ch4 = fileReader.read();
System.out.println((char)ch4);//
System.out.println(ch4);//-1
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {//在finally里边必须关闭IO流
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void test2() {
try {
FileReader fileReader = new FileReader("io.txt");
int ch = -1;
while ((ch = fileReader.read()) != -1) {
System.out.println((char)ch);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//----------Day12---------------
@Test
public void test3() {
try {
FileReader fileReader = new FileReader("io.txt");
char[] buffer = new char[10];
int length = -1;
//public int read(char[] cbuf)
//一次将10个字符读入到buffer数组里面
//返回:读取的字符数,如果已经达到流的末尾,返回-1
while ((length = fileReader.read(buffer)) != -1) {
System.out.println(length);
System.out.println(buffer);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Test
public void test4() {
//父类
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
fileReader = new FileReader("io.txt");
fileWriter = new FileWriter("io_back.txt");
char[] buffer = new char[10];
int length = -1;
//public int read(char[] cbuf)
//一次将10个字符读入到buffer数组里面
//返回:读取的字符数,如果已经达到流的末尾,返回-1
while ((length = fileReader.read(buffer)) != -1) {
System.out.println(length);
System.out.println(buffer);
//读出多少写多少,最后一次读出来的数据很有可能不够buffer数组的长度
fileWriter.write(buffer, 0, length);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//先打开的后关闭
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
3 字节流
@Test
public void test5() {
//FileInoutSteam 父类是InputSteam
FileInputStream fileInputStream = null;//经验 先生命成null 局部变量必须初始化
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream("baidu.png");
fileOutputStream = new FileOutputStream("baidu_back.png");
byte[] buffer = new byte[1024];
int length = -1;
while ((length = fileInputStream.read(buffer)) != -1){//赋值语句有结果 结果就是length值
System.out.println(length);
//fileOutputStream.write(buffer, 0, length);//这个不会多写
fileOutputStream.write(buffer);//会多写几个字节
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
4 对象流
ObjectInputStream、ObjectOutputStream
将对象写入文件的操作流ObjectOutputStream,称为序列化。
从流中读取对象的操作流程ObjectInputStream,称为反序列化。
java.io.NotSerializableException: com.situ.day13.Student
Serialize:序列化
/*
* 适度编码益脑,沉迷编码伤身,合理安排时间,享受快乐生活。
* Copyright @TangXJ
* Created by TangXJ
* Created&Used date: 2024/3/27 下午2:06 ~ 2024/3/27 下午3:39
* Modified date: 2024/3/27 下午3:39
*/
package com.sdust.day12;
import org.junit.Test;
import java.io.*;
public class Student implements Serializable {//实现一个接口
private Integer id;
private String name;
private Integer age;
private String gender;
public Student() {
}
public Student(Integer id, String name, Integer age, String gender) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer 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 + '\'' +
'}';
}
//对象流
@Test
public void test1() {
Student student = new Student();
student.setId(1);
student.setName("zhangsan");
student.setAge(23);
student.setGender("男");
//java.lang.RuntimeException: java.io.NotSerializableException: com.sdust.day12.Student//不能序列化的异常
//实现一个接口
ObjectOutputStream objectOutputStream = null;//不负责写文件 对象转换交给它ObjectOutputStream来完成
//负责把一个对象 做一个转换
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream("stu");
objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(student);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {//x先打开的后关闭
if (objectOutputStream != null){
try {
objectOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
@Test
public void test2() {
ObjectInputStream objectInputStream = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("stu");
objectInputStream = new ObjectInputStream(fileInputStream);
//Student student = objectInput.readObject();//报错 父类不能转换为子类
//Object object = new Student();
Student student = (Student) objectInputStream.readObject();
System.out.println(student);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
if (objectInputStream != null) {
try {
objectInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
这个Demo运行时要注释掉所有构造函数。
一般情况下:先打开的后关闭,后打开的先关闭。
另一种情况:看依赖关系,如果流A依赖于流B,先关闭流A,再关闭流B。