理解字符流和字节流,节点流和处理流、缓冲流、InputStreamReader、BufferInputStream、BufferReader...
DAY10.2 Java核心基础
IO流
字符流和字节流
字符流和字节流在每次处理数据的单位不同,一个是字符,一个是字节
如果复制文件类型是文本类型,字节流字符流都可以
如果复制的文件类型是非文本类型,则只能使用字节流,使用字符流会导致文件不可用
public static void main(String[] args) throws IOException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\img.png");
FileReader fileReader = new FileReader(file1);
FileWriter fileWriter = new FileWriter("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\img2.png");
int temp = 0;
while ((temp = fileReader.read()) != -1) {
fileWriter.write(temp);
}
fileWriter.close();
fileReader.close();
}
用字符流复制文件导致文件受损不可用,打开文件失败
但是字节流就可以完美复制,因为字节流每次操作的最小数据,什么数据格式都可以复制
public static void main(String[] args) throws IOException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\img.png");
File file2 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\img2.png");
InputStream inputStream = new FileInputStream(file1);
OutputStream outputStream = new FileOutputStream(file2);
int temp = 0;
while ((temp = inputStream.read()) != -1) {
outputStream.write(temp);
}
inputStream.close();
outputStream.close();
}
处理流
字节流是基础管道,字符流是在字节流基础上转化而来的
Java提供了完成转化的类,按照输入和输出两个方向分为输入转化流(InputStreamReader)和输出转化流(OutputStreamWriter)
InputStreamReader
public static void main(String[] args) throws IOException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\test3.txt");
InputStream inputStream = new FileInputStream(file1);
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
int i;
int num = 0;
while ((i=inputStreamReader.read())!=-1){
System.out.println(i);
num++;
}
inputStreamReader.close();
System.out.println(num);
}
InputStreamReader是Reader的子类,所以它是一个字符输入流
OutputStreamWriter
public static void main(String[] args) throws IOException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\test3.txt");
OutputStream outputStream = new FileOutputStream(file1);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
outputStreamWriter.write("今天天气怎么样");
outputStreamWriter.flush();
outputStreamWriter.close();
}
OutputStreamWriter是Writer的子类,所以它是一个字符输出流
缓冲流
为了减少对硬盘的资源开销,引入的缓冲流,自带缓冲区,可以一次性读取硬盘的部分输出存入缓冲区,再写入内存中
缓冲流属于处理流,不能直接关联文件操作,只能对已存在的节点流进行操作
如何区分节点流和处理流?
- 节点流:可以关联文件创建,有个构造函数传递file文件类进行创建
- 处理流:不能直接关联文件创建,不能通过构造函数传递file文件类进行创建
缓冲流又可以分为:
- 字节缓冲流:字节输入缓冲流、字节输出缓冲流
- 字符缓冲流:字符输入缓冲流、字符输出缓冲流
字节输入缓冲流(BufferInputStream)
public static void main(String[] args) throws IOException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\test3.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file1));
while (bufferedInputStream.available() != 0){
System.out.println(bufferedInputStream.read());
}
}
字节输出缓存流(BufferedInputStream)
public static void main(String[] args) throws IOException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\test3.txt");
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file1));
String content ="JDK(Java Development Kit)称为Java开发包或Java开发工具,\r\n是一个编写Java应用程序的开发环境";
bufferedOutputStream.write(content.getBytes());
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
字符输入缓存流(BufferReader),很好用,可以读取一行的数据
文件内容:
public static void main(String[] args) throws IOException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\test3.txt");
BufferedReader br = new BufferedReader(new FileReader(file1));
// String line;
// int count = 0;
// while ((line = br.readLine()) != null) {
// System.out.println(line);
// count++;
// }
// System.out.println(count);
int temp;
while ((temp = br.read()) != -1) {
System.out.println(temp);
}
}
输出:
可以看见44为逗号,13和10代表换行符 \n
中文字符需要的长度长一点,1个中文字符需要3个字节,这样每一个字符读取比字节读取效率更高,但是我们还有更加高效的方法
readLine() 方法:
public static void main(String[] args) throws IOException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\test3.txt");
BufferedReader br = new BufferedReader(new FileReader(file1));
String line;
int count = 0;
while ((line = br.readLine()) != null) {
System.out.println(line);
count++;
}
System.out.println(count);
}
输出:
BufferedReader有一个读取每行的方法,更加高效简洁
字符输出缓冲流(BufferedWriter )
BufferedWriter 提供了一个可以直接将字符串输出的方法 write(String str)
public static void main(String[] args) throws IOException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\test3.txt");
BufferedWriter bw = new BufferedWriter(new FileWriter(file1));
String content = "JDK(Java Development Kit)称为Java开发包或Java开发工具,\r\n是一个编写Java应用程序的开发环境";
bw.write(content);
bw.flush();
bw.close();
}
序列化和反序列化
将文件读取到内存中,以 byte、数组、char、String 类型展示的,同理我们也可以将内存中的数字或者字符串数据输出到文件中
如果我们需要将内存中的对象输出到文件中,或者从文件中读取数据并还原成内存中的对象,如何处理?
- 序列化:将内存中的对象输出到硬盘文件中进行保存
需要序列化的User类,必须实现Serializable接口
public class User implements Serializable {
private String name;
private int age;
public User(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 "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试接口:
public static void main(String[] args) throws IOException, ClassNotFoundException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\test3.txt");
User user = new User("张三", 18);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file1));
objectOutputStream.writeObject(user);
objectOutputStream.flush();
objectOutputStream.close();
}
写入到文件:
- 反序列化:从文件中读取数据并还原成内存中的对象
public static void main(String[] args) throws IOException, ClassNotFoundException {
File file1 = new File("H:\\JavaCode\\src\\main\\java\\com\\deepSeek\\shuwu\\Day10\\test3.txt");
User user = new User("张三", 18);
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file1));
Object o = objectInputStream.readObject();
User user1 = (User) o;
System.out.println(user1);
objectInputStream.close();
}
输出: