JAVA中IO流的相关使用(二)

一、缓冲流

  • 缓冲流是在原始流的基础上进行包装,它们的作用是用来提高原始流读写数据的性能。
    在这里插入图片描述

1、字节缓冲流

  • 作用:提高字节流读写数据的性能
  • 原理:字节缓冲输入流自带了8KB(8192)缓冲池;字节缓冲输出流也自带了8KB缓冲池。
  • 总结:功能上和原始流并无很大变化,性能上提升了。
    在这里插入图片描述
    try (
            InputStream is = new FileInputStream("io-app2/src/test01.txt");
            // 1、定义一个字节缓冲输入流包装原始的字节输入流
            InputStream bis = new BufferedInputStream(is);

            OutputStream os = new FileOutputStream("io-app2/src/test01_bak.txt");
            // 2、定义一个字节缓冲输出流包装原始的字节输出流
            OutputStream bos = new BufferedOutputStream(os);
    ){

        byte[] buffer = new byte[1024];
        int len;
        while ((len = bis.read(buffer)) != -1){
            bos.write(buffer, 0, len);
        }
        System.out.println("复制完成!!");

    } catch (Exception e) {
        e.printStackTrace();
    }

2、字符缓冲流

  • 作用:提高字符流读写字符数据的性能
  • 原理:字符缓冲输入流自带了8K(8192)的字符缓冲池;字符缓冲输出流也自带了8KB缓冲池。
    在这里插入图片描述
    try (
            Reader fr = new FileReader("io-app2\\src\\test04.txt");
            // 创建一个字符缓冲输入流包装原始的字符输入流
            BufferedReader br = new BufferedReader(fr);
    ){
//            char[] buffer = new char[3];
//            int len;
//            while ((len = br.read(buffer)) != -1){
//                System.out.print(new String(buffer, 0, len));
//            }
//            System.out.println(br.readLine());
//            System.out.println(br.readLine());
//            System.out.println(br.readLine());
//            System.out.println(br.readLine());

        String line; // 记住每次读取的一行数据
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

在这里插入图片描述

    try (
            Writer fw = new FileWriter("io-app2/src/test05out.txt", true);
            // 创建一个字符缓冲输出流管道包装原始的字符输出流
            BufferedWriter bw = new BufferedWriter(fw);
    ){

        bw.write('a');
        bw.write(97);
        bw.write('磊');
        bw.newLine();

        bw.write("我爱你中国abc");
        bw.newLine();

    } catch (Exception e) {
        e.printStackTrace();
    }

3、案例:字节缓冲流方式拷贝大文件

    // 复制的视频路径
    private static final String SRC_FILE = "D:\\resource\\线程池.avi";
    // 复制到哪个目的地
    private static final String DEST_FILE = "D:\\";
    
    ....................
    
    // 缓冲流按照一个一个字节数组的形式复制,速度极快,推荐使用!
    private static void copy() {
        long startTime = System.currentTimeMillis();
        try (
                InputStream is = new FileInputStream(SRC_FILE);
                BufferedInputStream bis = new BufferedInputStream(is, 64 * 1024);
                OutputStream os = new FileOutputStream(DEST_FILE + "4.avi");
                BufferedOutputStream bos = new BufferedOutputStream(os, 64 * 1024);
        ){
            byte[] buffer = new byte[1024 * 64]; // 32KB
            int len;
            while ((len = bis.read(buffer)) != -1){
                bos.write(buffer, 0, len);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("缓冲流使用字节数组复制耗时:" + (endTime - startTime) / 1000.0 + "s");
    }

二、转换流

  • 引出问题:如果代码编码和被读取的文本文件的编码是不一致的,使用字符流读取文本文件时就会出现乱码!
    在这里插入图片描述

1.字符输入转换流

  • 作用:解决不同编码时,字符流读取文本内容乱码的问题。

  • 解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
    在这里插入图片描述

    try (
            /**
             * test06.txt内容
             * 
             * 1床前明月光c
             * 2疑是地上霜b
             * 3低头思姑娘a
             * abcde
             */
            // 1、得到文件的原始字节流(GBK的字节流形式)
            InputStream is = new FileInputStream("io-app2/src/test06.txt");//该文件的编码是GBK
            // 2、把原始的字节输入流按照指定的字符集编码转换成字符输入流
            Reader isr = new InputStreamReader(is, "GBK");
            // 3、把字符输入流包装成缓冲字符输入流
            BufferedReader br = new BufferedReader(isr);
            ){
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

2.字符输出转换流

  • 作用:可以控制写出去的字符使用什么字符集编码。
  • 解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了
    在这里插入图片描述
      // 指定写出去的字符编码。
      try (
              // 1、创建一个文件字节输出流
              OutputStream os = new FileOutputStream("io-app2/src/test07out.txt");
              // 2、把原始的字节输出流,按照指定的字符集编码转换成字符输出转换流。
              Writer osw = new OutputStreamWriter(os, "GBK");
              // 3、把字符输出流包装成缓冲字符输出流
              BufferedWriter bw = new BufferedWriter(osw);
              ){
          bw.write("我是中国人abc");
          bw.write("我爱你中国123");

      } catch (Exception e) {
          e.printStackTrace();
      }

三、打印流

在这里插入图片描述

  • 作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。

1、PrintStream提供的打印数据的方案

在这里插入图片描述

2、PrintWriter提供的打印数据的方案

在这里插入图片描述

   try (
      // 1、创建一个打印流管道
//                PrintStream ps =
//                        new PrintStream("io-app2/src/itheima08.txt", Charset.forName("GBK"));
//                PrintStream ps =
//                        new PrintStream("io-app2/src/itheima08.txt");
      PrintWriter ps =
              new PrintWriter(new FileOutputStream("io-app2/src/test08.txt", true));
      ){
      ps.println(97);
      ps.println('a');
      ps.println("我爱你中国abc");
      ps.println(true);
      ps.println(99.5);

      // ps.write(97); // 'a'
           
   } catch (Exception e) {
       e.printStackTrace();
   }

3、打印流重定向

    // 这2句会打印到控制台
    System.out.println("老骥伏枥");
    System.out.println("志在千里");

    try ( PrintStream ps = new PrintStream("io-app2/src/test09.txt"); ){

        // 把系统默认的打印流对象改成自己设置的打印流
        System.setOut(ps);
        // 这2句会打印到test09.txt文件中
        System.out.println("烈士暮年");
        System.out.println("壮心不已");
    } catch (Exception e) {
        e.printStackTrace();
    }

PrintStream和PrintWriter的区别

  • 打印数据的功能上是一模一样的:都是使用方便,性能高效(核心优势)
  • PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。
  • PrintWriter继承自字符输出流Writer,因此支持写字符数据出去。

四、数据流

在这里插入图片描述

1、数据输出流

  • 作用:允许把数据和其类型一并写出去。
    在这里插入图片描述
     try (
             // 1、创建一个数据输出流包装低级的字节输出流
             DataOutputStream dos =
                     new DataOutputStream(new FileOutputStream("io-app2/src/test10out.txt"));
             ){
         dos.writeInt(97);
         dos.writeDouble(99.5);
         dos.writeBoolean(true);
         dos.writeUTF("干得漂亮666!");

     } catch (Exception e) {
         e.printStackTrace();
     }

2、数据输入流

  • 作用:用于读取数据输出流写出去的数据。
    在这里插入图片描述
     try (
             DataInputStream dis =
                     new DataInputStream(new FileInputStream("io-app2/src/test10out.txt"));
             ){
         int i = dis.readInt();
         System.out.println(i);

         double d = dis.readDouble();
         System.out.println(d);

         boolean b = dis.readBoolean();
         System.out.println(b);

         String rs = dis.readUTF();
         System.out.println(rs);
     } catch (Exception e) {
         e.printStackTrace();
     }

五、序列化流

在这里插入图片描述

1、对象字节输出流

  • 作用:可以把Java对象进行序列化:把Java对象存入到文件中去。
  • 注意:对象如果要参与序列化,必须实现序列化接口(java.io.Serializable)
    在这里插入图片描述
     try (
             // 2、创建一个对象字节输出流包装原始的字节 输出流。
             ObjectOutputStream oos =
                     new ObjectOutputStream(new FileOutputStream("io-app2/src/test11out.txt"));
             ){
         // 1、创建一个Java对象。
         User u = new User("admin", "张三", 32, "666888xyz");

         // 3、序列化对象到文件中去
         oos.writeObject(u);
         System.out.println("序列化对象成功!!");

     } catch (Exception e) {
         e.printStackTrace();
     }

2、对象字节输入流

  • 作用:可以把Java对象进行反序列化:把存储在文件中的Java对象读入到内存中来。
    在这里插入图片描述
	   try (
	            // 1、创建一个对象字节输入流管道,包装 低级的字节输入流与源文件接通
	            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("io-app2/src/test11out.txt"));
	            ){
	        User u = (User) ois.readObject();
	        System.out.println(u);
	    } catch (Exception e) {
	        e.printStackTrace();
	    }

User对象定义

public class User implements Serializable {
    private String loginName;
    private String userName;
    private int age;
    // transient 这个成员变量将不参与序列化。
    private transient String passWord;

    public User() {
    }

    public User(String loginName, String userName, int age, String passWord) {
        this.loginName = loginName;
        this.userName = userName;
        this.age = age;
        this.passWord = passWord;
    }
    ........//省略getter、setter
}

六、补充:IO框架

1、什么是 框架?

  • 解决某类问题,编写的一套类、接口等,可以理解成一个半成品,大多框架都是第三方研发的。
  • 好处:在框架的基础上开发,可以得到优秀的软件架构,并能提高开发效率。
  • 框架的形式:一般是把类、接口等编译成class形式,再压缩成一个.jar结尾的文件发行出去。

2、什么是IO框架?

  • 封装了Java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。

3、Commons-io

  • Commons-io是apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率。
    在这里插入图片描述
     FileUtils.copyFile(new File("io-app2\\src\\test01.txt"), new File("io-app2/src/a.txt"));
     FileUtils.copyDirectory(new File("D:\\resource\\私人珍藏"), new File("D:\\resource\\私人珍藏3"));
     FileUtils.deleteDirectory(new File("D:\\resource\\私人珍藏3"));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LogicArk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值