字符流
它和字节流的区别是读取的单位是不同的 .字节流是按照单个字节进行读写操作.
字符流是按照单个字符的单位进行读写操作.字符流专门用来处理的文本字符文件的.字节流是用来处理文本文件或者二进制文件的.
字符输入流
java.io.Reader[C] - 顶级的字符输入流 - 抽象类
BufferedReader[C] - 带缓冲功能的字符流
public BufferedReader(Reader in) { this(in, defaultCharBufferSize); }
提供的方法 String readLine();//每次读取文本文件的一整行的数据,如果读取不到[到达文件的末尾了],返回false
FileReader[C] - 字符流中的节点流 - 具备真正的字符文件的读写操作的.
demo
package tech.aistar.day13;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* 本类用来演示: 字符输入流
*
* @author: success
* @date: 2021/8/6 1:40 下午
*/
public class ReaderHelloDemo {
public static void main(String[] args) {
//1. 确定流
//2. 确定源头
//3. 循环读取
//4. 关闭流 - 可以采取语法糖 - JVM去自行关闭
//demo - 用来读取文本文件,然后将内容输出到控制台上去
try(BufferedReader in = new BufferedReader(new FileReader("src/tech/aistar/day13/Book.java"))){
//一行一行进行读取
String line = null;
//循环读取
while(true){
line = in.readLine();//读取一整行的数据,若读取不到,则返回false
//循环退出的条件
if(line == null)
break;
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符输出流
java.io.Writer[C] - 顶级的字符输出流 - 抽象类
PrintWriter[C] - 自带缓存功能
PrintWriter(Writer out); //第二个参数是是否自动刷新缓存 //缓存里面的数据什么时候会被同步到磁盘上 //1. 缓存中的数据满的时候 - 会自动刷新 //2. 缓存中的数据还不足以撑满这个缓存 - close或者flush - 强制刷新缓存 PrintWriter(Writer out, boolean autoFlush);
FileWriter[C] -字符流中的节点流 - 具备真正的字符文件的读写操作的.
构造方法: 1. FileWriter(String path);//写到哪里去,目标的绝对/相对路径 2. FileWriter(String path,boolean append);//第二个参数代表的是是否追加写入.如果append设置成true.支持分批次的写 和分批次的读 - 都是字符串
demo
package tech.aistar.day13;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 本类用来演示: 字符输出流
*
* @author: success
* @date: 2021/8/6 1:57 下午
*/
public class WriterHelloDemo {
public static void main(String[] args) {
test02();
}
public static void test03(){
//1. 构建一个自动刷新,但是能够实现追加写入的功能.
//第一个true - 代表的是是否追加写入 - true
//第二个true - 是否自动刷新缓存,设置成true之后,那么就不需要在程序代码中手动刷新,不需要再去写out.flush();
// 推荐 - 1. 构建一个自动刷新的输出流 2. 程序代码的之后还是推荐手动刷新out.flush()3. 依然需要关闭流 - jvm
try(PrintWriter out =
new PrintWriter(new FileWriter("src/tech/aistar/day13/writer.txt",true),true)){
//因为语法糖 - close()操作 - 底层就是关闭流之前,会强制刷新缓存.
//有可能有部分学生的计算机,它没有达到强制刷新缓存的效果
//场景 - 内存中的数据不能写入到磁盘上的这文件中的[文件中的内容是空的]
//print方法以及println方法
//print方法写入之后,后面是没有加一个\n
//println方法写入之后,后面是有一个\n
//把内存中的数据持久化到磁盘中的文件中.
//out.print("web前端很好玩!");
out.println("c不好玩!");
//推荐在结束的时候,手动刷新一下缓存
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void test02(){
//1. 构建一个不自动刷新,但是能够实现追加写入的功能.
try(PrintWriter out = new PrintWriter(new FileWriter("src/tech/aistar/day13/writer.txt",true))){
//因为语法糖 - close()操作 - 底层就是关闭流之前,会强制刷新缓存.
//有可能有部分学生的计算机,它没有达到强制刷新缓存的效果
//场景 - 内存中的数据不能写入到磁盘上的这文件中的[文件中的内容是空的]
//print方法以及println方法
//print方法写入之后,后面是没有加一个\n
//println方法写入之后,后面是有一个\n
//把内存中的数据持久化到磁盘中的文件中.
//out.print("web前端很好玩!");
out.println("c不好玩!");
//推荐在结束的时候,手动刷新一下缓存
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void test01(){
//1. 构建的是一个不自动刷新,不追加写入的字符输出流
//每次都会覆盖原来的文件,并且在第一次写入的时候,会自动创建这个文件的.
try(PrintWriter out = new PrintWriter(new FileWriter("src/tech/aistar/day13/writer.txt"))){
//因为语法糖 - close()操作 - 底层就是关闭流之前,会强制刷新缓存.
//有可能有部分学生的计算机,它没有达到强制刷新缓存的效果
//场景 - 内存中的数据不能写入到磁盘上的这文件中的[文件中的内容是空的]
//print方法以及println方法
//print方法写入之后,后面是没有加一个\n
//println方法写入之后,后面是有一个\n
//把内存中的数据持久化到磁盘中的文件中.
out.print("python很好玩!");
//推荐在结束的时候,手动刷新一下缓存
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件的拷贝
package tech.aistar.day13;
import java.io.*;
/**
* 本类用来演示: 字符流来实现文件的拷贝操作
*
* @author: success
* @date: 2021/8/6 2:37 下午
*/
public class FileCopyReaderDemo {
public static void main(String[] args) {
copyFile("src/tech/aistar/day13/FileDemo.java","src/tech/aistar/day13/FileDemo_副本.java");
}
/**
* 文件的拷贝
* @param src 原文件的路径
* @param target 目标文件的路径
*/
public static void copyFile(String src,String target){
//1. 构建流 - 源头和目标的确定
try(BufferedReader in = new BufferedReader(new FileReader(src));
PrintWriter out = new PrintWriter(new FileWriter(target),true)){
//2. 定义一个变量 - 用来保存每次读取到的一行数据
String line = null;
//3. 循环读取
while(true){
line = in.readLine();//读取一整行,读不到,则返回null
//循环退出的条件
if(line == null)
break;
//写一行出去
out.println(line);
}
System.out.println("文件拷贝成功!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结笔试
- 常见的字节流和字符流
- 装饰器的设计模式
- 难一点的知识点 - 同步[打电话]IO/异步[发短信]IO区别,阻塞IO/非阻塞IO区别
- BufferedInputStream - 内置的缓冲数组 - 8kb
补充 - 破坏单例
单例设计模式 - 保证在整个应用程序中,某个类的具体的实例永远只有1个 - 多线程下也是一个 - 双重锁检测
对象的序列化和反序列化可以破坏这种单例,如何破坏?
解决方案: 单例的第四个版本 - 枚举类型来实现单例模式
package tech.aistar.day13; import tech.aistar.design.singleton.version03.Singleton03; import java.io.*; /** * 本类用来演示: 对象的序列化和反序列化可以破坏单例的 * * @author: success * @date: 2021/8/6 3:06 下午 */ public class ObjectSingletonDemo { public static void main(String[] args) { Singleton03 s1 = Singleton03.getInstance(); String path = "src/tech/aistar/day13/singleton.txt"; //把这个对象写入到文件中 writeObject(s1,path); //读 Singleton03 s2 = readObject(path);//反序列化之后,并没有走构造,直接操作的内存 System.out.println(s1 == s2);//false } //对象的序列化 public static void writeObject(Singleton03 s,String path){ try(ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(path))){ //写 out.writeObject(s); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //对象的反序列化 public static Singleton03 readObject(String path){ Singleton03 s = null; try(ObjectInputStream in = new ObjectInputStream(new FileInputStream(path))){ //读 s = (Singleton03) in.readObject(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return s; } }