1.缓冲流

1.1、缓冲流概述、字节缓冲流使用

image-20230810161814288.png

  • 缓冲流概述
    • 缓冲流也称高效流、或者高级流。之前学习的字节流可以称为原始流
    • 作用:缓冲流自带缓冲区,可以提高原始字节流、字符流读写数据的性能
  • 字节缓冲流性能优化原理
    • 字节缓冲输入流自带了8KB缓冲池,以后直接从缓冲池读取数据,所以性能较好
    • 字节缓冲输出流自带了8KB缓冲池,数据直接写入到缓冲池中,些数据性能极高
  • 字节缓冲流
    • 字节缓冲输入流:BufferedInputStream,提高字节输入流读取数据的性能
    • 字节缓冲输出流:BufferedOutputStream,提高字节输出流读取数据的性能

image-20230810161823597.png

public class Test {
    public static void main(String[] args){
        try(
                //创建原始输入流
                InputStream is = new FileInputStream("E:/TestPhoto/mv.mp4");
                //字节缓冲输入流
                BufferedInputStream bis = new BufferedInputStream(is);
                //创建原始输出流
                OutputStream os = new FileOutputStream("E:/TestPhoto/copy.mp4");
                //字节缓冲输出流
                BufferedOutputStream bos = new BufferedOutputStream(os);
           ){
            byte[] buffer = new byte[1024];
            int len;//记录读取的字节数,方便写的时候,读多少写多少,避免错误信息
            while((len = bis.read(buffer)) != -1){
                bos.write(buffer,0,len);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

1.2、字节缓冲流的性能分析

【需求】:分别使用低级字节流喝高级字节缓冲流拷贝大视频,记录耗时

public static final String URL = "E:/TestPhoto/mv.mp4";
    public static final String COPY_URL = "E:/TestPhoto";
    public static void main(String[] args) {
        //copy01();太慢,淘汰
        copy02();
        copy03();
        copy04();
    }
    //使用低级字节流一个一个自己的复制
    public static void copy01(){
        long startTime = System.currentTimeMillis();
        try(
                InputStream is = new FileInputStream(URL);
                OutputStream os = new FileOutputStream(COPY_URL+"/copy01.mp4");
                ){
            int len;
            while ((len = is.read()) != -1) {
                os.write(len);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        long beginTime = System.currentTimeMillis();
        System.out.println("低级字节流按照一个一个字节的形式复制文件耗时:"+(startTime-beginTime)/1000.0+"s");
    }
    //使用低级的字节流按照一个一个字节数组的形式复制
    public static void copy02(){
        long startTime = System.currentTimeMillis();
        try(
                InputStream is = new FileInputStream(URL);
                OutputStream os = new FileOutputStream(COPY_URL+"/copy02.mp4");
                ){
            byte[] buffer = new byte[1024];
            int len;
            while((len = is.read(buffer)) != -1){
                os.write(buffer,0,len);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        long beginTime = System.currentTimeMillis();
        System.out.println("使用低级的字节流按照一个一个字节数组的形式复制文件耗时:"+(startTime-beginTime)/1000.0+"s");
    }
    //缓冲流一个一个字节复制
    public static void copy03(){
        long startTime = System.currentTimeMillis();
        try(
                //缓冲输入流
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(URL));
                //缓冲输出流
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(COPY_URL+"/copy03.mp4"));
                ){
            int len;
            while((len = bis.read()) != -1){
                bos.write(len);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        long beginTime = System.currentTimeMillis();
        System.out.println("缓冲流一个一个字节复制文件耗时:"+(startTime-beginTime)/1000.0+"s");
    }
    //缓冲流一个一个字节数组复制
    public static void copy04(){
        try(
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(URL));
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(COPY_URL+"/copy04.mp4"));
                ){
            byte[] buffer = new byte[1024];
            int len;
            while((len = bis.read(buffer)) != -1){
                bos.write(buffer,0,len);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        long startTime = System.currentTimeMillis();
        long beginTime = System.currentTimeMillis();
        System.out.println("低级字节流按照一个一个字节的形式复制文件耗时:"+(startTime-beginTime)/1000.0+"s");
    }

1.3、字符缓冲流

image-20230810161840242.png

  • 字符缓冲输入流
    • 字符缓冲输入流:BufferedReader
    • 作用:提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能

image-20230810161930961.png

【字符缓冲流新增功能】

image-20230810161937611.png

public class Test {
    public static void main(String[] args) {
        try(
                //1.创建文件字符输入流,与文件接通
                Reader r = new FileReader("Demo/src/data03");
                //2.吧低级字符流包装为字符缓冲流
                BufferedReader br = new BufferedReader(r);
                ){
        String line;
        while((line = br.readLine())!=null){
            System.out.println(line);
        }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
  • 字符缓冲输出流
    • 字符缓冲输出流:BufferedWriter
    • 作用:提高字符输出流写取数据的性能,除此之外多了换行功能

image-20230810161944099.png

【字符缓冲流新增功能】

image-20230810161948788.png

public class Test {
    public static void main(String[] args) {
        try(
                //1.创建文件字节输出流与目标文件接通
                Writer w = new FileWriter("Demo/src/out.txt",true);//追加管道【不清空之前的数据,继续拼接】

                //2.包装为字符输出缓冲流
                BufferedWriter bw = new BufferedWriter(w);
                ){
            //a.public void write(int c):写一个字符出去
            bw.write(97);
            bw.write('b');
            bw.write('马');
            bw.newLine();//换行
            //b.public void wirte(String c):写一个字符串出去
            bw.write("马浩楠");
            bw.newLine();//换行
            //c.public void write(char[] buffer):写一个字符数组出去
            bw.write("张林燕".toCharArray());
            bw.newLine();//换行
            //d.public void write(String c,int pos,int len):写字符串的一部分出去
            bw.write("I am tired,but I am poor so I must every effort to earn。暗黑哈哈哈",0,55);
            //e.public void write(char[] buffer,int pos,int len):写字符数组的一部分出去
            bw.write("爱你",0,1);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

【需求】:吧《出师表》的文章顺序进行恢复到一个新的文件中

public class Test {
    public static void main(String[] args) {
        List<String> lines = new ArrayList<>();
        try(
                //字符缓冲输入流
                BufferedReader br = new BufferedReader(new FileReader("Demo/src/out.txt"));
                //字符缓冲输出流
                BufferedWriter bw = new BufferedWriter(new FileWriter("Demo/src/sortOut.txt"));
                ){
            String line;
            while((line = br.readLine()) != null){
                lines.add(line);
            }
            List<String> sizes = new ArrayList<>();//用来存储文字前面的一,二...,来按照索引定义大小
            Collections.addAll(sizes,"一","二","三","四","五","陆","柒","八","九");
            lines.sort((o1,o2) -> {
                return sizes.indexOf(o1.substring(0,o1.indexOf("."))) - sizes.indexOf(o2.substring(0,o2.indexOf(".")));
            });
            for (String s : lines) {
                bw.write(s);
                bw.newLine();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

2.转换流

2.1、问题引出:不同编码读取乱码问题

  • 如果代码编码和文件编码不一致,使用字符流直接读取会乱码
  • 代码编码是UTF-8,文件编码使用GBK,使用字符流读取则乱码

2.2、字符输入转换流

image-20230810161958828.png

  • 字符输入转换流:InputStreamReader,可以把原始的字节流按照指定编码准换成字符输入流

image-20230810162006146.png

public class InputStreamReaderDemo {
    public static void main(String[] args) {
        try(
                InputStream is = new FileInputStream("E:/TestPhoto/data03.txt");
                //吧原始字节流转换为字符输入流
                Reader r = new InputStreamReader(is,"GBK");//以指定的GBK编码转换为字符输入流,解决字符集不同导致的乱码
                //包赚为缓冲字符输入流
                BufferedReader br = new BufferedReader(r);
        ){
            String line;
            while((line = br.readLine()) != null){
                System.out.println(line);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

2.3、字符输出转换流

image-20230810162016499.png

  • 字符输入转换流:OutputStreamWriter,可以把字节输出流按照指定编码转换成字符输出流

image-20230810162023325.png

public class OutputSreamWriterDemo {
    public static void main(String[] args) {
        try(
                OutputStream os = new FileOutputStream("Demo/src/data04.txt");
                //将字节流转换为字符输出流
                OutputStreamWriter osw = new OutputStreamWriter(os,"GBK");//以GBK的字符集写内容出去
                //包装为缓冲字符输出流
                BufferedWriter bw = new BufferedWriter(osw);
                ){
            bw.write("爱你中国");
            bw.write("爱你中国");
            bw.write("爱你中国");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3.序列化对象

3.1、对象序列化

  • 作用:以内存为基准,把内存中的数据存储到磁盘文件中,称为对象序列化
  • 使用到的流是对象字节输出流:ObjectOutputStream

image-20230810162038328.png

  • 使用到的流是对象字节输出流:ObjectOutputStream

image-20230810162045884.png

  • ObjectOutputStream序列化方法

image-20230810162051283.png

【Student】

public class Student implements Serializable {
    //申请序列化的版本号码
    //序列化的版本号与反序列化的版本号必须一致才可反序列化
    public static final long serialVersionUID = 1;
    private String name;
    private Integer age;
    //transient 修饰后,不序列化该属性(避免敏感信息出现泄露)
    private transient String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Student() {
    }

    public Student(String name, Integer age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
}

【ObjectOutputStreamDemo】

public class ObjectOutputStreamDemo {
    public static void main(String[] args) {
        try(
                ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Demo/src/obj.txt"));
                ){
            Student student = new Student("浩楠",22,"河南省禹州市");
            oos.writeObject(student);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3.2、对象反序列化

image-20230810162101193.png

  • 作用:以内存为基准,把存储到磁盘文件中的对象数据恢复成内存中的对象,称为反序列化
  • 使用到的流是对象字符输入流:ObjectInputStream

image-20230810162107220.png

  • ObjectInputStream序列化方法

image-20230810162112832.png

【Student同上】

【ObjectInputStreamDemo】

public class ObjectInputStreamDemo {
    public static void main(String[] args) {
        try(
                ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Demo/src/obj.txt"));
                ){
            Student student = (Student)ois.readObject();
            System.out.println(student);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

4.打印流

4.1、PrintStream、PrintWriter

image-20230810162121483.png

  • 打印流

    • 作用:打印流可以实现方便、高效的打印数据到文件中去。打印流一般是指:PrintStream、PrintWriter两个类
    • 可以实现打印什么数据就是什么数据,例如打印正数97写出去就是97,打印boolean的true,写出去也就是true。
  • PrintStream

image-20230810162141787.png

  • PrintWriter

image-20230810162148530.png

  • PrintStream与PrintWriter区别
    • 打印数据功能上是一模一样的,都是使用方便,性能高效
    • PrintStream继承自字节输出流OutputStream,支持些字节数据的方法
    • PrintWriter继承自输出流Writer,支持写字符数据出去
public class Demo1 {
    public static void main(String[] args) {
        try(
                //PrintStream ps = new PrintStream("Demo/src/printStream.txt");
                PrintStream ps = new PrintStream(new FileOutputStream("Demo/src/printStream.txt",true));//追加
                //PrintWriter ps = new PrintWriter("Demo/src/printStream.txt");//打印功能上两者没区别
                ){
            ps.println(97);
            ps.println('b');
            ps.println(true);
            ps.println("打印什么就是什么!");

            //PrintWriter写的功能
            //ps.println("嗯哈");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

4.2、输出语句的重定向

  • 属于打印流的一种应用,可以把输出语句打印到指定位置

image-20230810162159704.png

public class Demo2 {
    public static void main(String[] args) throws Exception{
        System.out.println("1111");
        System.out.println("2222");
        //改变输出语句的位置(重定向)
        PrintStream ps = new PrintStream("Demo/src/relocate.txt");
        System.setOut(ps);
        System.out.println("2222");
        System.out.println("3333");
        ps.close();
    }
}

5.补充:Properties

image-20230810162205776.png

  • Properties属性集对象
    • 其实就是Map集合,但一般不会当集合用,因为HashMap更好用
  • Properties核心作用:
    • Properties代表的是一个属性文件,可以把字节对象中的键值对信息存放到一个属性文件中去
    • 属性文件:后缀是.properties结尾的文件,里面的内容都是 key = value,后续做系统配置信息使用的。
  • API

image-20230810162213345.png

public class Demo1 {
    public static void main(String[] args) throws Exception{
        Properties p = new Properties();
        p.setProperty("admit","010220");
        p.setProperty("h","aaaaa");

        p.store(new FileWriter("Demo/src/user.properties"),"this is users,don't delete");
    }
}
public class Demo2 {
    public static void main(String[] args) throws Exception{
        Properties p = new Properties();
        System.out.println(p);
        p.load(new FileReader("Demo/src/user.properties"));
        System.out.println(p);
        System.out.println("------------------");
        System.out.println(p.getProperty("admit"));
    }
}

6.补充:IO框架

  • commons-io概述
    • commons-io是apache开源基金组织提供的一组有关IO操作的类库,可以提高IO功能开发的效率
    • commons-io工具包提供了很多有关io操作的类,有两个主要的类FileUtils,IOUtils
  • FileUtils主要有如下方法:

image-20230810162222186.png

  • 导包
    • 项目创建文件夹:lib
    • 将commons-io-2.6.jar文件复制到lib文件夹中
    • 在jar文件右键,选择:Add ad Library
public class Demo {
    public static void main(String[] args) throws  Exception{
        //1.完成文件复制
        IOUtils.copy(new FileInputStream("E:/TestPhoto/jichi.jpg"),new FileOutputStream("E:/TestPhoto/chi.jpg"));
        //2.完成文件复制到某个文件夹下
        FileUtils.copyFileToDirectory(new File("E:/TestPhoto/jichi.jpg"),new File("E:/new/"));
        //3.完成文件夹复制到某个文件夹下
        FileUtils.copyDirectoryToDirectory(new File("E:/TestPhoto/jichi.jpg"),new File("E:/"));
        //JDK1.7后,自身也做了一些一行代码完成复制的操作
        Files.copy(Path.of("E:/TestPhoto/jichi.jpg"),Path.of("E:/TestPhoto/chi.jpg"));
    }
}

results matching ""

    No results matching ""