字符流


字符流

它和字节流的区别是读取的单位是不同的 .字节流是按照单个字节进行读写操作.

字符流是按照单个字符的单位进行读写操作.字符流专门用来处理的文本字符文件的.字节流是用来处理文本文件或者二进制文件的.

字符输入流

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();
        }
    }
}

总结笔试

  1. 常见的字节流和字符流
  2. 装饰器的设计模式
  3. 难一点的知识点 - 同步[打电话]IO/异步[发短信]IO区别,阻塞IO/非阻塞IO区别
  4. 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;
    }
}

文章作者: 码农耕地人
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 码农耕地人 !
  目录