问题引入

  1. hello world!,你好,世界!

使用字节输入流,读取以上文件,每次读取1个字节,然后再转换成字符,输出到控制台。

    @Test
    public void demo1() throws  IOException {
        FileInputStream fis = new FileInputStream("other\\chinese_input.txt");

        int b;
        while((b = fis.read()) != -1) {
            System.out.print(new String(new byte[]{(byte)b}));
        }

        fis.close();
    }
hello world!������������������

打印到控制台的结果是乱码,因为中文在当前文件中占3个字节(中文占几个字节受文件编码格式的影响),每次读取1个字节,只是读取到了中文的一半,在码表中找不到这一个字节该怎么展示,所以输出到控制台为“?”,
解决这一问题,可以使用内存输出流

内存输出流概述

内存输出流可以向内存中写数据, 把内存当作一个缓冲区, 写出之后可以一次性获取出所有数据。

常用成员方法

  • 创建对象: new ByteArrayOutputStream()
  • 写出数据: write(int), write(byte[])
  • 获取数据: toByteArray()

    演示

      /**
       * FileInputStream读取中文的时候出现了乱码
       *
       * 解决方案
       * 1.字符流读取
       * 2.ByteArrayOutputStream
       * @throws IOException
       */
      @Test
      public void demo2() throws IOException {
          FileInputStream fis = new FileInputStream("other\\chinese_input.txt");
          //在内存中创建了可以增长的内存数组
          ByteArrayOutputStream baos = new ByteArrayOutputStream();            
    
          //将读取到的数据逐个写到内存中
          int b;
          while((b = fis.read()) != -1) {
              baos.write(b);                                                    
          }
    
          //将缓冲区的数据全部获取出来,并赋值给arr数组
          byte[] arr = baos.toByteArray();        
    
          //new String(arr)与toString()方法的区别是,他可以使用指定字符集将字节转换为字符串
          System.out.println(new String(arr));                                
          System.out.println("==========================");
    
          //将缓冲区的内容转换为了字符串,在输出语句中也可以省略调用toString方法
          System.out.println(baos.toString());                                
    
          /**
           * ByteArrayOutputStream无需关闭流,
           * 因为它并没有对接硬盘上的文件,而是在内存中开辟了一块区域,
           * 就像使用集合一样,不使用了,它会被JVM垃圾回收释放。
           */
          //fis.close();
      }
    
    hello world!你好,世界!
    ==========================
    hello world!你好,世界!