Java教程

Java--IO

本文主要是介绍Java--IO,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

io概述(掌握)

什么是io

  • input 输入
  • output 输出

为什么学习io

  • 在操作系统中,数据想要存储都是以文件的形式进行存储到外部设备
  • 内存有限,需要跟外部设备有交互

java中如何实现io

通过流模型(通过创建输入流,输出流去实现的)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m4WMhyFL-1642513915118)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115094140302.png)]

io的分类

按照流向分(以内存为参数)

  • 输入流 :外设→内存
  • 输出流: 内存→外设

按照数据类型分

  • 字节流: 一连串的01二进制数据,0000 0000 , 单位是字节 1B
  • 字符流:一连串的字符序列(理解为一种文化符号,你好,abc,の)

4个抽象基类

字节输出流:OutputStream

字节输入流:InputStream

字符输出流:Writer

字符输入流:Reader

由这4个抽象基类派生出的子类都已其父类名字作为后缀的

FileOutputStream

FileInputStream

什么时候应该用什么流

一般对于文本数据,采用字符流.

字节流是万能的(在不知道什么样的数据格式的时候)

字节流(重点)

字节输出流

抽象基类OutputStream

此抽象类是表示输出字节流的所有类的超类

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oEx2MON1-1642513915121)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115095230662.png)]

成员方法

voidclose() 关闭此输出流并释放与此流有关的所有系统资源。
voidflush() 刷新此输出流并强制写出所有缓冲的输出字节。
voidwrite(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。
voidwrite(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract voidwrite(int b) 将指定的字节写入此输出流。

注意

write 的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略

具体子类

FileOutputStream字节文件输出流

文件输出流是用于将数据写入 File

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PJcwX5o0-1642513915123)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115100015525.png)]

构造方法

FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。

Demo

    /*
     * FileOutputStream构造方法
     * 创建日期:2022/1/15 10:04
     * @return void
     */
    @Test
    public void myTest1() throws FileNotFoundException {
        // FileOutputStream(File file)
        File file = new File("a.txt");
        FileOutputStream out = new FileOutputStream(file);

        FileOutputStream outputStream = new FileOutputStream(new File("a.txt"));

        // FileOUtputStream(String fileName)
        FileOutputStream outputStream1 = new FileOutputStream("a.txt");
        
    }

成员方法

voidwrite(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。
voidwrite(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
voidwrite(int b) 将指定字节写入此文件输出流。

Demo

    /*
     * write方法
     * 写数据的步骤
     * 1.创建字节输出流对象
     * 2.写数据 write方法
     * 3.close
     * 创建日期:2022/1/15 10:08
     * @return void
     */
    @Test
    public void myTest2() throws IOException {
        //System.out.println(System.getProperty("user.dir"));
        // 创建字节输出流对象
        FileOutputStream out = new FileOutputStream("a.txt");

        // write
        // write(int b)
        //writeSingle(out);

        // write(byte[] b)
        String s = "abc";
        byte[] bytes = s.getBytes();
        //writeMulti(out, bytes);
        // 此时,文件内容是啥
        // 1.aabc  2.abc

        // write(byte[] b,int off,int len)
        out.write(bytes, 0, bytes.length);
        

        // close
        out.close();
    }

    private void writeMulti(FileOutputStream out, byte[] bytes) throws IOException {
        out.write(bytes);
    }

    private void writeSingle(FileOutputStream out) throws IOException {
        out.write(97);
    }

注意事项

  • 当我们创建字节输出流的时候,发生了什么?

    • 在创建之前,jvm会向操作系统中找这个文件是否存在
    • 如果不存在,帮我们创建
    • 如果存在,覆盖原来已有的,重新写入
  • 如果实现文件内容追加?

    • 利用构造方法FileOutputStream(String fileName, boolean append) 把append设置为true

    •     /*
           * 实现文件追加功能
           * 创建日期:2022/1/15 10:45
           * @return void
           */
          @Test
          public void myTest4() throws IOException{
              // 创建字节输出流对象 利用带append的构造方法
              FileOutputStream out = new FileOutputStream("a.txt", true);
              // write数据
              out.write("abc".getBytes());
              // close
              out.close();
          }
      
  • 如何实现换行功能?

    • 换行符

    •     /*
           * 实现换行功能
           * 创建日期:2022/1/15 10:48
           * @return void
           */
          @Test
          public void myTest5() throws IOException{
              // 创建字节输出流对象
              FileOutputStream out = new FileOutputStream("a.txt");
              // write数据
              out.write("abc".getBytes());
              // 写入换行符
              // "\r\n"
              out.write("\r\n".getBytes());
              out.write("abc".getBytes());
      
              // "\r"
              out.write("\r".getBytes());
              out.write("abc".getBytes());
      
              // "\n"
              out.write("\n".getBytes());
              out.write("abc".getBytes());
              // 默认换行符
              out.write(System.lineSeparator().getBytes());
              out.write("abc".getBytes());
      
      
              // close
              out.close();
          }
      
  • 异常处理

    • try-catch

      •     /*
             * 异常处理 try-catch
             * 创建日期:2022/1/15 10:56
             * @return void
             */
            @Test
            public void myTest6(){
                // 创建字节输出流对象
                FileOutputStream out = null;
                try {
                    out = new FileOutputStream("a.txt");
                    // write数据
                    out.write("abc".getBytes());
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    try {
                        // 判断out是否为null
                        if (out != null) {
                            // close
                            out.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
        
            }
        
    • try-with-resources

      • //语法
        try(资源,实现了AutoCloseable接口的类){
            // 当执行完try中的代码,会自动释放资源
        }catch{
            
        }finally{
            
        }
        
      •     /*
             * try-with-resources
             * 创建日期:2022/1/15 11:06
             * @return void
             */
            @Test
            public void  myTest7() {
                try(FileOutputStream out = new FileOutputStream("a.txt")) {
                    // write 数据
                    out.write("aaa".getBytes());
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        
      • 证明自动释放

      • class A implements AutoCloseable{
        
            @Override
            public void close() throws Exception {
                System.out.println("close方法执行了!");
            }
        
            public void func(){
                System.out.println("func 执行了!");
            }
        
        }
        
            /*
             * 证明自动释放资源
             * 创建日期:2022/1/15 11:10
             * @return void
             * @author 景天
             */
            @Test
            public void myTest8(){
                try (A a = new A()){
                    // 执行func方法
                    a.func();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        
  • 为什么要close?

    • io资源属于操作系统资源,不属于jvm资源,不能够进行垃圾回收,只能显式的通过close方法去释放
    • 只有不属于jvm资源,都需要释放,一般都叫close

BufferedOutputStream字节缓冲输出流

该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DQIPNEIt-1642513915126)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117112630374.png)]

构造方法

BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。默认缓冲区大小是8KB
BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。

像这种需要底层流作为参数的,叫做包装流

Demo

    /*
     * BufferedOutputSteam 构造方法
     * 创建日期:2022/1/17 11:37
     */
    @Test
    public void myTest6() throws IOException{
        // 更多操作BufferedOutputStream(OutputStream out)
        // 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
        FileOutputStream out = new FileOutputStream("a.txt");
        BufferedOutputStream bo = new BufferedOutputStream(out);

        BufferedOutputStream bo2 = new BufferedOutputStream(new FileOutputStream(
                new File("a.txt")));


        // BufferedOutputStream(OutputStream out,  int size)
        // 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
        BufferedOutputStream bo3 = new BufferedOutputStream(new FileOutputStream("a.txt"),1024);
    }

带缓冲区的输入输出流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W9bUX2LM-1642513915128)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117113628095.png)]

成员方法

3个write方法

    /*
     * BufferedOutputStream write
     * 创建日期:2022/1/17 11:43
     * @return void
     */
    @Test
    public void myTest7() throws IOException{
        // 创建缓冲字节输出流对象
        BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("a.txt"));
        // write方法写数据
        // write(int b)
        bo.write(97);
        bo.write("\r\n".getBytes());

        // write(byte[] b)
        bo.write("哈哈哈".getBytes());
        bo.write(System.lineSeparator().getBytes());

        // write(byte[] b, int off ,int len)
        bo.write("abc".getBytes(), 0, 2);

        // 执行flush操作
        bo.flush();

        // close
        bo.close();
    }

注意:

  • BufferedOutputStream带缓冲区,一定记得flush操作
  • 如果忘记flush,一定要close

为什么close会执行flush方法?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cFbZ6mJm-1642513915130)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117115120196.png)]

字节输入流

抽象基类InputStream

象类是表示字节输入流的所有类的超类

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4plnNwLq-1642513915132)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115111703052.png)]

成员方法

abstract intread() 从输入流中读取数据的下一个字节。
intread(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
intread(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。

注意事项

  • read() 从输入流中读取数据的下一个字节。返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。 readData
  • read(byte[] b) 读入缓冲区的总字节数;如果因为已经到达流末尾而不再有数据可用,则返回 -1。readCount

具体子类

FileInputStream字节文件输入流

FileInputStream 从文件系统中的某个文件中获得输入字节

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yS5wTYiu-1642513915134)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115112628236.png)]

构造方法

FileInputStream(File file) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

Demo

    /*
     * FileInputStream 构造方法
     * 创建日期:2022/1/15 11:27 
     * @return void
     */
    @Test
    public void myTest9() throws IOException{
        // FileInputStream(File file)
        FileInputStream in = new FileInputStream(new File("a.txt"));

        // FileInputStream(String fileName)
        FileInputStream inputStream = new FileInputStream("a.txt");
    }

成员方法

intread() 从此输入流中读取一个数据字节。
intread(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
intread(byte[] b, int off, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
    /*
     * FileInputStream  read方法
     * 读取数据
     * 1.创建字节输入流对象
     * 2.read方法读取数据
     * 3.close
     * 创建日期:2022/1/15 11:30
     * @return void
     */
    @Test
    public void myTest10() throws IOException{
        // 创建字节输入流对象
        FileInputStream in = new FileInputStream("a.txt");
        // read方法读取数据
        // read() 读取单个字节,返回值是readData
        //readSingle(in);

        // read(byte[] b)
        // 这个字节数组相当于一个容器
        byte[] bytes = new byte[1024];
        // readCount代表了读取到的字节的个数
        // readMulti(in, bytes);

        // read(byte[] b,int off , int len)
        int readCount = in.read(bytes, 1, 3);
        System.out.println(readCount);
        System.out.println(new String(bytes,1,readCount));

        // close
        in.close();
    }

    private void readMulti(FileInputStream in, byte[] bytes) throws IOException {
        int readCount = in.read(bytes);
        System.out.println("readCount = " + readCount);
        String s = new String(bytes, 0, readCount);
        System.out.println(s);
    }

    private void readSingle(FileInputStream in) throws IOException {
        int readData = in.read();
        System.out.println(((char) readData));
        int readData2 = in.read();
        System.out.println(((char) readData2));
        int readData3 = in.read();
        System.out.println(((char) readData3));

        int readData4 = in.read();
        System.out.println(readData4);
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PRdB0hR2-1642513915135)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115113722846.png)]

细节

    @Test
    public void myTest1() throws IOException {
        // 创建1个字节输入流
        FileInputStream in = new FileInputStream("a.txt");
        // 读取数据 read(byte [] b)
        byte[] bytes = new byte[4];
        int readCount1 = in.read(bytes);
        System.out.println("readCount1 = " + readCount1);
        System.out.println(new String(bytes));

        // 再读取1次
        int readCount2 = in.read(bytes);
        System.out.println("readCount2 = " + readCount2);
        System.out.println(new String(bytes,0,readCount2));

        // close
        in.close();
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hB1S3tKH-1642513915136)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117095929946.png)]

循环读取

    /*
     * 循环读取
     * 创建日期:2022/1/17 10:00
     * @return void
     */
    @Test
    public void myTest2() throws IOException{
        // 创建字节输入流对象
        FileInputStream in = new FileInputStream("a.txt");
        // 读取数据 循环读
        // 简单方式
        // readWhile1(in);
        // 高阶方式
        // 读取单个字节

        // 表示读取到的字节值
        // readWhile2(in);

        // 读取多个字节 字节数组方式
        // 表示读取到的字节的个数
        int readCount;
        byte[] bytes = new byte[1024];
        while ((readCount = in.read(bytes)) != -1) {
            System.out.println(new String(bytes,0,readCount));
        }


        // close
        in.close();





    }

    private void readWhile2(FileInputStream in) throws IOException {
        int readData;
        while ((readData = in.read()) != -1) {
            System.out.print(((char) readData));
        }
    }

    private void readWhile1(FileInputStream in) throws IOException {
        int readData;
        while (true) {
            readData = in.read();
            if (readData == -1) {
                break;
            }
            System.out.println(((char) readData));
        }
    }

BufferedInputStream缓冲字节输入流

BufferedInputStream 为另一个输入流添加一些功能

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MISh4SHu-1642513915137)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117142323589.png)]

构造方法

BufferedInputStream(InputStream in) 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 默认缓冲区大小是8KB
BufferedInputStream(InputStream in, int size) 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
    /*
     * BufferedInputStream 构造方法
     * 创建日期:2022/1/17 14:25
     * @return void
     */
    @Test
    public void myTest8() throws IOException{
        //| BufferedInputStream(InputStream in)      
        // 创建一个 BufferedInputStream 
        // 并保存其参数,即输入流  in,以便将来使用。 |
        BufferedInputStream bi = new BufferedInputStream(
                new FileInputStream("a.txt"));


        //| BufferedInputStream(InputStream in,  int size)       
        // 创建具有指定缓冲区大小的 BufferedInputStream  并保存其参数,即输入流 in,以便将来使用。 |
        BufferedInputStream bi2 = new BufferedInputStream(
                new FileInputStream("a.txt"),1024);
        
    }

成员方法

3个read方法

    /*
     * BufferedInputStream  read
     * 创建日期:2022/1/17 14:28
     * @return void
     */
    @Test
    public void myTest9() throws IOException{
        // 创建输入流对象
        BufferedInputStream bi = new BufferedInputStream(
                new FileInputStream("a.txt"));
        // read方法
        // 读取到的字节值
        // read() 单个字节
        //readSingle(bi);


        // read(byte[] b) 字节数组
        byte[] bytes = new byte[1024];
        //readMulti(bi, bytes);


        // read(byte[] b, int off ,int len)
        int readCount = bi.read(bytes, 0, bytes.length);
        System.out.println(new String(bytes,0,readCount));

        // close
        bi.close();
    }

    private void readMulti(BufferedInputStream bi, byte[] bytes) throws IOException {
        // 表示读取到的字节个数
        int readCount = bi.read(bytes);
        System.out.println(new String(bytes,0,readCount));
    }

    private void readSingle(BufferedInputStream bi) throws IOException {
        int readData = bi.read();
        System.out.println(readData);
    }

文件复制功能

思路

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KOpOFyzy-1642513915139)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117101602649.png)]

文本文件

 /*
     * 文本文件复制
     * 创建日期:2022/1/17 10:16
     * @return void
     */
    @Test
    public void myTest3() throws IOException{
        // 创建字节输入流对象
        FileInputStream in = new FileInputStream("D:\\a.txt");
        //创建字节输出流对象
        FileOutputStream out = new FileOutputStream("copy_a.txt");

        // 边读边写 判断条件  -1
        // 采用单字节的方式
        // copy1(in, out);

        // 字节数组的方式
        byte[] bytes = new byte[1024];
        // 表示读取到的字节个数
        int readCount;
        while ((readCount = in.read(bytes)) != -1) {
            // write
            out.write(bytes, 0, readCount);
        }

        // 循环结束 意味着复制完成

        // close
        in.close();
        out.close();

    }

    private void copy1(FileInputStream in, FileOutputStream out) throws IOException {
        // 表示读取到的字节值
        int readData;
        while ((readData = in.read()) != -1) {
            // 写数据
            out.write(readData);
        }
    }

图片文件

单字节耗时 177ms

字节数组方式耗时 2ms

视频文件

单字节 耗时: 15379ms

字节数组方式 耗时: 24ms

哪种方式效率更高?

从消耗的时间上看,字节数组的方式效率更高.数组的方式减少了跟操作系统交互

举例:

现在我在京东上买了5个快递,我家离快递站10公里.快递小哥送快递

单字节: 一次送1个快递,跑5次

字节数组: 东哥说了,咱们都是兄弟,给每个兄弟配了宝马.开着宝马送快递,一下送5个快递,跑1次.

缓冲流实现文件复制

    /*
     * 使用缓冲流实现文件复制
     * 创建日期:2022/1/17 14:35
     * @return void
     */
    @Test
    public void myTest10() throws IOException{
        // 创建缓冲输入流对象
        BufferedInputStream in = new BufferedInputStream(
                new FileInputStream("D:\\aa.mp4"));
        // 创建缓冲输出流对象
        BufferedOutputStream out = new BufferedOutputStream(
                new FileOutputStream("copy_aa.mp4"));
        // 边读边写
        // 单字节
        long start = System.currentTimeMillis();
        // copy1(in, out);

        // 多字节
        int readCount;
        byte[] bytes = new byte[1024];
        while ((readCount = in.read(bytes)) != -1) {
            out.write(bytes, 0, readCount);
        }

        long end = System.currentTimeMillis();
        System.out.println("耗时: " + (end-start) + "ms");

        // close
        in.close();
        out.close();
    }

    private void copy1(BufferedInputStream in, BufferedOutputStream out) throws IOException {
        int readData;
        while ((readData = in.read()) != -1) {
            out.write(readData);
        }
    }

字符流(重点)

为什么有字符流

  • 读取文件,处理英文和数字 (没有问题)
  • 处理带有中文(可能有问题)
    /*
     * 用字节流读取文件内容:
     * 1.英文 数字
     * 2.带有中文的内容
     * 创建日期:2022/1/17 15:10
     * @return void
     */
    @Test
    public void myTest1() throws IOException {
        // 创建输入流对象
        FileInputStream in = new FileInputStream("a.txt");
        // read方法读取数据
        //int readData;
        //while ((readData = in.read()) != -1) {
        //    // 打印
        //    System.out.print(((char) readData));
        //}

        // 用字节数组的方式去处理
        //int readCount;
        //byte[] bytes = new byte[11];
        //while ((readCount = in.read(bytes)) != -1) {
        //
        //    System.out.println(new String(bytes,0,readCount));
        //}

        String s = "abc001你好";
        byte[] bytes = s.getBytes();
        System.out.println(Arrays.toString(bytes));
        // close
        in.close();
    }

一个字符是怎么存储在计算机中的

基于某个编码表,存的时候是这个字符在编码表中所对应的整数值(编码值)

编解码

  • 编码
    • 基于某个编码表,把字符数据转化为编码值存储到计算机的过程(把人看懂的东西转化为计算机看懂的东西)
  • 解码
    • 基于某个编码表,把编码值转化为字符数据的过程(把计算机看懂的东西转化人看懂的东西)

编码表

中文编码表 你 0x0001

日文编码表 の 0x0001

ASCII:美国标准信息交换码。
用一个字节的7位可以表示。0000 0000 - 0111 1111
ISO8859-1:拉丁码表。欧洲码表 0000 0000 - 1111 11111
用一个字节的8位表示。

GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。 2个字节表示1个中文字符
GB18030:GBK的取代版本
BIG-5码 :通行于台湾、香港地区的一个繁体字编码方案,俗称“大五码”。

Unicode:国际标准码,融合了多种文字。

UTF-8:可变长度来表示一个字符。
UTF-8不同,它定义了一种“区间规则”,这种规则可以和ASCII编码保持最大程度的兼容:

它将Unicode编码为00000000-0000007F的字符,用单个字节来表示 0111 1111 = 7F
它将Unicode编码为00000080-000007FF的字符用两个字节表示
它将Unicode编码为00000800-0000FFFF的字符用3字节表示

1字节 0xxxxxxx
2字节 110xxxxx 10xxxxxx
3字节 1110xxxx 10xxxxxx 10xxxxxx 中文采用的是3个字节表示1个中文字符

utf-16:

jvm使用的编码表,用2个字节来编解码,表示1个字符

char : 2 字节

工作中常用的编码表

ASCII

GBK 2个字节表示1个中文

ISO8859-1 1个字节表示1个字符

utf-8 3个字节表示1个中文

乱码问题

  • 产生的原因:编码解码不一致
  • 解决:使编解码保持一致

默认的编码表

  • idea当中 默认的编码表 是 UTF-8
  • Windows系统中,默认采用的是GBK
   /*
    * 默认编码表
    * 创建日期:2022/1/17 16:12
    * @return void
    */
   @Test
   public void myTest2() {
       System.out.println(Charset.defaultCharset());
   }

java中如何实现编解码

    /*
     * 默认编码表
     * 创建日期:2022/1/17 16:12
     * @return void
     */
    @Test
    public void myTest2() {
        System.out.println(Charset.defaultCharset());
    }

    /*
     * java中实现编解码
     * 创建日期:2022/1/17 16:17
     * @return void
     */
    @Test
    public void myTest3() throws UnsupportedEncodingException {
        // 定义1个字符串
        String s = "你好";
        // 编码
        // getBytes()
        // 使用平台的默认字符集将此 String 编码为 byte 序列,
        // 并将结果存储到一个新的 byte 数组中。

        // byte[] getBytes(String charsetName)
        //使用指定的字符集将此 String 编码为 byte 序列,
        // 并将结果存储到一个新的 byte 数组中
        byte[] encodingGbk = s.getBytes("GBk");
        System.out.println(Arrays.toString(encodingGbk));

        // 把编码值转化为字符串  解码
        // String(byte[] bytes)
        // 通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
        //String s1 = new String(encodingGbk);
        //System.out.println(s1);

        // String(byte[] bytes, String charsetName)
        // 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
        String strGbk = new String(encodingGbk, "GBk");
        System.out.println(strGbk);
    }
    

字符流的本质

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lla80QXE-1642513915140)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117163914148.png)]

字符输出流

抽象基类Writer

写入字符流的抽象类

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jNRzeXSL-1642513915142)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117170117935.png)]

成员方法

voidwrite(char[] cbuf) 写入字符数组。
abstract voidwrite(char[] cbuf, int off, int len) 写入字符数组的某一部分。
voidwrite(int c) 写入单个字符。
voidwrite(String str) 写入字符串。
voidwrite(String str, int off, int len) 写入字符串的某一部分。

注意

写入单个字符。要写入的字符包含在给定整数值的 16 个低位中,16 高位被忽略。

具体子类

OutputStreamWriter转换流

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J5zSrci3-1642513915142)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117170711030.png)]

构造方法

OutputStreamWriter(OutputStream out) 创建使用默认字符编码的 OutputStreamWriter。
OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的 OutputStreamWriter。
    /*
     * 转换流的构造方法
     * 创建日期:2022/1/17 17:09
     * @return void
     */
    @Test
    public void myTest4() throws IOException{
        // 更多操作OutputStreamWriter(OutputStream out) 
        // 创建使用默认字符编码的 OutputStreamWriter。
        OutputStreamWriter out = 
                new OutputStreamWriter(new FileOutputStream("a.txt"));

        // OutputStreamWriter(OutputStream out,  String charsetName) 
        // 创建使用指定字符集的 OutputStreamWriter。
        OutputStreamWriter out2 = 
                new OutputStreamWriter(new FileOutputStream("a.txt"), "GBk");
    }

成员方法

voidwrite(char[] cbuf) 写入字符数组。
abstract voidwrite(char[] cbuf, int off, int len) 写入字符数组的某一部分。
voidwrite(int c) 写入单个字符。
voidwrite(String str) 写入字符串。
voidwrite(String str, int off, int len) 写入字符串的某一部分。
    /*
     * OutputStreamWriter  写数据
     * 创建日期:2022/1/17 17:11
     * @return void
     */
    @Test
    public void myTest5() throws IOException{
        // 创建输出流对象
        OutputStreamWriter out =
                new OutputStreamWriter(new FileOutputStream("a.txt"));
        String s = "我变强了,也变秃了";
        char[] chars = s.toCharArray();

        // write方法写数据
        // write(int c) 写入单个字符
        // writeSingle(out, chars);

        // write(char[] c) 写入字符数组
        out.write(chars);
        out.write(System.lineSeparator());

        // write(char[] c,int off ,int len ) 写入字符数组部分
        out.write(chars, 0, 4);
        out.write(System.lineSeparator());


        // write(String s)  直接写字符串
        out.write("嘤嘤嘤,小拳拳捶你胸口");
        out.write(System.lineSeparator());

        
        // write(String s, int off , int len)直接写字符串
        out.write("我是一朵带刺的玫瑰",0,6);


        // flush
        out.flush();

        // close
        out.close();

    }

    private void writeSingle(OutputStreamWriter out, char[] chars) throws IOException {
        for (int i = 0; i < chars.length; i++) {
            out.write(chars[i]);
        }
    }

FileWriter简化流

用来写入字符文件的便捷类

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nkcaZBnn-1642513915145)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118100030850.png)]

构造方法

FileWriter(File file) 根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。
FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
    /*
     * FileWriter 构造方法
     * 创建日期:2022/1/18 10:02 
     * @return void
     */
    @Test
    public void myTest2() throws IOException{
        FileWriter fileWriter = new FileWriter(new File("a.txt"));

        FileWriter fileWriter1 = new FileWriter("a.txt");
        FileWriter fileWriter2 = new FileWriter("a.txt",true);

    }

成员方法

5个write 3 + 2

    /*
     * FileWriter 写数据
     * 创建日期:2022/1/18 10:05
     * @return void
     */
    @Test
    public void myTest3() throws IOException{
        // 创建输出流对象
        FileWriter fileWriter = new FileWriter("a.txt");
        // write方法写数据
        // write(int c)
        // write(char [] c)
        // write(char[] c , int off ,int len)
        // write(String str)
        // write(String str, int off ,int len)

        fileWriter.write("宝,我今天输液了,什么夜,想你的夜");
        // flush
        fileWriter.flush();
        // close
        fileWriter.close();
    }

BufferedWriter字符缓冲输出流

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SnJcRwZq-1642513915147)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118105329370.png)]

构造方法

BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。默认缓冲区大小16KB
BufferedWriter(Writer out, int sz) 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。
 @Test
    public void myTest6() throws IOException {
        //| BufferedWriter(Writer out)
        // 创建一个使用默认大小输出缓冲区的缓冲字符输出流。默认缓冲区大小16KB |
        BufferedWriter bw = 
                new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt")));
        
        BufferedWriter bw2 = new BufferedWriter(new FileWriter("a.txt"));

        //| BufferedWriter(Writer out,  int sz)
        // 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。 |
        BufferedWriter bw3 = new BufferedWriter(new FileWriter("a.txt"), 1024);
    }

成员方法

5个write方法 3 +2

独有的方法

voidnewLine() 写入一个行分隔符。
    /*
     * BufferedWriter 方法
     * 创建日期:2022/1/18 11:12
     * @return void
     */
    @Test
    public void myTest7() throws IOException{
        // 创建输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
        // write方法写数据
        bw.write("哈哈哈哈哈");
        // 独有的方法 newLine()
        bw.newLine();
        bw.write("呵呵呵呵呵");

        // flush
        bw.flush();
        // close
        bw.close();
    }

字符输入流

抽象基类Reader

用于读取字符流的抽象类

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bvbuvLSM-1642513915148)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117172439471.png)]

成员方法

intread() 读取单个字符。
intread(char[] cbuf) 将字符读入数组。
abstract intread(char[] cbuf, int off, int len) 将字符读入数组的某一部分。

注意

  • read() 返回作为整数读取的字符,范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1 readData去表示
  • 读取的字符数,如果已到达流的末尾,则返回 -1 readCount去表示

具体子类

InputStreamReader转换流

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ndgFl8o-1642513915150)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117173045555.png)]

构造方法

InputStreamReader(InputStream in) 创建一个使用默认字符集的 InputStreamReader。
InputStreamReader(InputStream in, String charsetName) 创建使用指定字符集的 InputStreamReader。
    /*
     * InputStreamReader 构造方法
     * 创建日期:2022/1/17 17:32
     * @return void
     */
    @Test
    public void myTest6() throws IOException{
        //| InputStreamReader(InputStream in) 
        // 创建一个使用默认字符集的 InputStreamReader。 |
        InputStreamReader in = 
                new InputStreamReader(new FileInputStream("a.txt"));

        //| InputStreamReader(InputStream in, String charsetName)
        // 创建使用指定字符集的 InputStreamReader。 |

        InputStreamReader in2 = 
                new InputStreamReader(new FileInputStream("a.txt"), "utf-8");
    }

成员方法

intread() 读取单个字符。
intread(char[] cbuf) 将字符读入数组。
abstract intread(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
    /*
     * InputStreamRead 读取数据
     * 创建日期:2022/1/17 17:34
     * @return void
     */
    @Test
    public void myTest7() throws IOException{
        // 创建输入流对象
        InputStreamReader in =
                new InputStreamReader(new FileInputStream("a.txt"));
        // read方法读取数据
        // read() 读取单个字符
        // 代表了读取到的字符值
        // readSingle(in);

        // read(char [])
        char[] chars = new char[1024];
        // readMulti(in, chars);

        // read(char [], int off ,int len)
        in.read(chars, 1, 10);

        // close
        in.close();
    }

    private void readMulti(InputStreamReader in, char[] chars) throws IOException {
        // 表示的是读取到的字符的个数
        int readCount = in.read(chars);
        System.out.println(new String(chars,0,readCount));
    }

    private void readSingle(InputStreamReader in) throws IOException {
        int readData = in.read();
        System.out.println(((char) readData));
    }

使用指定字符集

    @Test
    public void myTest8() throws IOException{
        // 读取gbk编码的数据

        // 创建输入流对象
        InputStreamReader in =
                new InputStreamReader(new FileInputStream("b.txt"),"gbk");
        // read
        char[] chars = new char[1024];
        int readCount = in.read(chars);
        System.out.println(new String(chars,0,readCount));
        // close
        in.close();
    }

FileReader简化流

用来读取字符文件的便捷类

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qrzkp0hY-1642513915151)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118101015508.png)]

构造方法

FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。
FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader。

成员方法

3个read方法

    /*
     * FileReader 读取数据
     * 创建日期:2022/1/18 10:11
     * @return void
     */
    @Test
    public void myTest4() throws IOException{
        // 创建输入流对象
        FileReader reader = new FileReader("a.txt");
        // read()
        //readSingle(reader);


        // read(char[] c)
        char[] chars = new char[1024];
        //readMulti(reader, chars);

        // read(char[] c, int off ,int len)

        int readCount = reader.read(chars, 1, 10);

        // close
        reader.close();
    }

    private void readMulti(FileReader reader, char[] chars) throws IOException {
        int readCount = reader.read(chars);
        System.out.println(new String(chars,0,readCount));
    }

    private void readSingle(FileReader reader) throws IOException {
        // 代表读取的字符值
        int readData = reader.read();
        System.out.println(((char) readData));
    }

BufferedReader缓冲流

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oeGs2ARp-1642513915151)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118111721721.png)]

构造方法

BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。默认缓冲区16KB
BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。

成员方法

3个read方法

StringreadLine() 读取一个文本行
包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
    /*
     * BufferedReader 方法
     * 创建日期:2022/1/18 11:21
     * @return void
     */
    @Test
    public void myTest8() throws IOException {
        // 创建输入流对象那个
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        // read读取数据
        //readSingle2(br);

       // readMulti2(br);

        // 自己独有的方法readLine() 一次读一行数据
        //String s = br.readLine();
        //System.out.println(s);
        //String s2 = br.readLine();
        //System.out.println(s2);
        //String s3 = br.readLine();
        //System.out.println(s3);


        // readLine循环读取数据
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        

        // close
        br.close();
    }

    private void readMulti2(BufferedReader br) throws IOException {
        char[] chars = new char[1024];
        int readCount = br.read(chars);
        System.out.println(new String(chars,0,readCount));
    }

    private void readSingle2(BufferedReader br) throws IOException {
        int readData = br.read();
        System.out.println(((char) readData));
    }

简化流 VS 转化流

  • 继承关系上: 转化流是简化流的父类
  • 使用角度:简化流方便, 转化流麻烦
  • 简化流不能指定字符集,只能使用默认的字符集,转化流可以指定字符集

使用字符流去复制文件

文本文件 : 没有问题

非文本文件: 有问题

所以用的时候字符流只针对文本文件

    /*
     * 字符流复制文件
     * 创建日期:2022/1/18 9:48
     * @return void
     */
    @Test
    public void myTest1() throws IOException {
        // 文本文件
        // 创建输入流对象
        InputStreamReader in =
                new InputStreamReader(new FileInputStream("D:\\aa.mp4"));
        // 创建输出流对象
        OutputStreamWriter out =
                new OutputStreamWriter(new FileOutputStream("copy_aa.mp4"));
        // 边读边写
        char[] chars = new char[1024];
        int readCount;
        while ((readCount = in.read(chars)) != -1) {
            out.write(chars, 0, readCount);
        }
        // flush
        out.flush();

        // close
        out.close();
        in.close();
        
            
    }

其他流(了解)

数据流

字节流向文件中写个1000, 写个3.14

    @Test
    public void  myTest1() throws IOException {
        // 创建输出流对象
        FileOutputStream out = new FileOutputStream("b.txt");
        // write方法写数据
        //out.write(1000);
        //out.write(3.14);
        // close
        out.close();
    }

DataOutputStream

数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XXUSXrHw-1642513915152)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118143607610.png)]

构造方法

DataOutputStream(OutputStream out) 创建一个新的数据输出流,将数据写入指定基础输出流。

成员方法

每一种java基本数据类型都有1个write方法与之对应

比如 writeInt(int i)…

    /*
     * 向文件中写入整数1000
     * 创建日期:2022/1/18 14:38
     * @return void
     */
    @Test
    public void myTest2()  throws IOException{
        // writeData();


        // 使用数据输入流去读取
        // 创建输入流对象
        DataInputStream in = new DataInputStream(new FileInputStream("b.txt"));
        // readInt()  readDouble()

        int i = in.readInt();
        System.out.println("i = " + i);

        double v = in.readDouble();
        System.out.println("v = " + v);




        // close
        in.close();



    }

    private void writeData() throws IOException {
        // DataOutputStream(OutputStream out)
        // 创建一个新的数据输出流,将数据写入指定基础输出流。
        // 创建输出流对象
        DataOutputStream out = new DataOutputStream(new FileOutputStream("b.txt"));
        // writeInt
        out.writeInt(1000);

        out.writeDouble(3.14);

        // close
        out.close();
    }
    public static void main(String[] args) throws IOException {
        write();
        read();
    }

    private static void read() throws FileNotFoundException, IOException {
        DataInputStream dis = new DataInputStream(
                new FileInputStream("dos.txt"));
        byte b = dis.readByte();
        System.out.println(b);
        short s = dis.readShort();
        System.out.println(s);
        int i = dis.readInt();
        System.out.println(i);
        long l = dis.readLong();
        System.out.println(l);
        float f = dis.readFloat();
        System.out.println(f);
        double d = dis.readDouble();
        System.out.println(d);
        char ch = dis.readChar();
        System.out.println(ch);
        boolean bb = dis.readBoolean();
        System.out.println(bb);
        dis.close();
    }

    private static void write() throws IOException {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(
                "dos.txt"));
        dos.writeByte(1);
        dos.writeShort(20);
        dos.writeInt(300);
        dos.writeLong(4000);
        dos.writeFloat(12.34f);
        dos.writeDouble(12.56);
        dos.writeChar('a');
        dos.writeBoolean(true);
        dos.close();
    }

DataInputStream

数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aSuRtP5u-1642513915154)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118144425838.png)]

构造方法

DataInputStream(InputStream in) 使用指定的底层 InputStream 创建一个 DataInputStream。

成员方法

每一个java基本数据类型都有1个与之相对应的read方法

比如

readInt()…

注意

按照怎么样的方式去写, 就要按照相同的方式去读取数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-In5R4gbx-1642513915155)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118145528223.png)]

打印流

打印流的核心思想

练习:

定义1个Printer类

定义4个方法

  • printInt(int i) 专门打印int类型的数据,输出到文件中
  • printIntLn(int i) 专门打印int类型的数据,输出到文件中,并且换行
  • printDouble(double d) 专门打印double类型的数据,输出到文件中
  • printDoubleLn(double d) 专门打印double类型的数据,输出到文件中,并且换行

成员变量

  • 输出流对象
package com.cskaoyan._02otherstream;

import java.io.IOException;
import java.io.OutputStream;

/**
 * @description:
 * @date: 2022/1/18 15:12
 **/

/*
需求:
定义1个Printer类

定义4个方法

- printInt(int i)    专门打印int类型的数据,输出到文件中
- printIntLn(int i) 专门打印int类型的数据,输出到文件中,并且换行
- printDouble(double d)  专门打印double类型的数据,输出到文件中
- printDoubleLn(double d)  专门打印double类型的数据,输出到文件中,并且换行

成员变量

- 输出流对象
 */
public class Printer {
    // 定义成员变量
    OutputStream out;

    public Printer(OutputStream out) {
        this.out = out;
    }

    // 定义成员方法
    // - printInt(int i)    专门打印int类型的数据,输出到文件中
    public void printInt(int i) throws IOException {
        String s = String.valueOf(i);
        out.write(s.getBytes());
    }


    //printIntLn(int i) 专门打印int类型的数据,输出到文件中,并且换行
    public void printIntLn(int i) throws IOException {
        String s = String.valueOf(i);
        out.write(s.getBytes());
        out.write(System.lineSeparator().getBytes());
    }

    // - printDouble(double d)  专门打印double类型的数据,输出到文件中
    public void printDouble(double d) throws IOException{
        String s = String.valueOf(d);
        out.write(s.getBytes());
    }

    // - printDoubleLn(double d)  专门打印double类型的数据,输出到文件中,并且换行
    public void printDoubleLn(double d) throws IOException{
        String s = String.valueOf(d);
        out.write(s.getBytes());
        out.write(System.lineSeparator().getBytes());

    }

    // close 关闭资源
    public void close() throws IOException {
        out.close();
    }
}




    /*
     * Printer 测试
     * 创建日期:2022/1/18 15:22
     * @return void
     * @author 景天
     */
    @Test
    public void myTest3() throws IOException{
        // 创建Printer对象
        Printer printer = new Printer(new FileOutputStream("a.txt"));
        // 调用Printer方法
        // printInt
        printer.printIntLn(999);
        // printDouble
        printer.printDouble(6.28);
        // close 调用Printer的close
        printer.close();
    }

PrintStream字节打印流

PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CUB7ZcFJ-1642513915156)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118150102139.png)]

构造方法

PrintStream(File file) 创建具有指定文件且不带自动行刷新的新打印流。
PrintStream(OutputStream out) 创建新的打印流。
PrintStream(OutputStream out, boolean autoFlush) 创建新的打印流。
PrintStream(String fileName) 创建具有指定文件名称且不带自动行刷新的新打印流。

成员方法

每一个java基本数据类型都有1个与之相对应的print方法

比如: print(int i)

print(double d)…

PrintWriter字符打印流

向文本输出流打印对象的格式化表示形式

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q3dUsYx5-1642513915157)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118150610615.png)]

构造方法

PrintWriter(File file) 使用指定文件创建不具有自动行刷新的新 PrintWriter。
PrintWriter(OutputStream out) 根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream 创建新的 PrintWriter。
PrintWriter(String fileName) 创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out) 创建不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out, boolean autoFlush) 创建新 PrintWriter。

成员方法

每一个java基本数据类型都有1个与之相对应的print方法

比如: print(int i)

print(double d)…

打印流的特点

  • 只能操作目的地,不能操作数据来源。
    • 都是输出流,没有1个输入流与之相对
  • 可以操作任意类型的数据。
    • 每个java基本数据类型都有1个print方法与之对应,把不同类型的数据转化为字符串
  • 如果启动了自动刷新,能够自动刷新。
    • autoFlush - boolean 变量;如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vly5XT15-1642513915158)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118160205897.png)]
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OSevfu9O-1642513915159)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118160312470.png)]
  • 可以操作文件的流
    • 可以传File ,也可以传String fileName

标准输入流与标准输出流

标准输入流

  • System.in
  • 默认输入设备 键盘
  • 本质: 是一个普通的字节输入流

标准输出流

  • System.out
  • 默认输出设备: 显示器
  • 本质: 字节打印流 PrintStream

练习:

利用System.in 完成Scanner的nextLine()的功能。

分析:

nextLine() 接收键盘输入 一行字符串

System.in 是1个普通字节输入流

想到BufferedReader当中的readLine()

    /*
     *利用System.in 完成Scanner的nextLine()的功能。
        分析:

        nextLine() 接收键盘输入 一行字符串

        System.in 是1个普通字节输入流

        想到BufferedReader当中的readLine()
     * 创建日期:2022/1/18 16:12
     * @return void
     */
    @Test
    public void myTest6() throws IOException{
        // 创建BufferedReader对象
        BufferedReader br =
                new BufferedReader(new InputStreamReader(System.in));

        // 完成Scanner的nextLine()
        // readLine()
        // readOneLine(br);

        // 实现多次输入
        // 当我们输入的值是 gun 终止程序结束
        String line;
        while ((line = br.readLine()) != null) {
            if ("gun".equals(line)) {
                break;
            }

            System.out.println(line);
        }

        br.close();

    }

    private void readOneLine(BufferedReader br) throws IOException {
        System.out.println("before");
        String s = br.readLine();
        System.out.println("after");

        System.out.println(s);
    }

对象流(序列化流与反序列化流)

为什么有?

Student s = new Student("zs",20)

序列化

把对象数据转化为二进制数据,持久化保存

反序列化

把二进制数据还原回对象数据

ObjectOutputStream

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储

只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码

writeObject 方法用于将对象写入流中。所有对象(包括 String 和数组)都可以通过 writeObject 写入。可将多个对象或基元写入流中。必须使用与写入对象时相同的类型和顺序从相应 ObjectInputstream 中读回对象。

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TmnHTRI5-1642513915160)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118164212189.png)]

构造方法

ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream。

成员方法

voidwriteObject(Object obj) 将指定的对象写入 ObjectOutputStream。

ObjectInputStream

ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化

继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m1JosnLq-1642513915162)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118164300414.png)]

构造方法

ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream。

成员方法

ObjectreadObject() 从 ObjectInputStream 读取对象
    /*
     * 序列化 反序列化
     * 创建日期:2022/1/18 16:34
     * @return void
     */
    @Test
    public void myTest7() throws IOException, ClassNotFoundException {
        // 序列化操作
        // writeObj();
        
        // 反序列化操作
        // 创建输入流对象
        ObjectInputStream in =
                new ObjectInputStream(new FileInputStream("b.txt"));
        // readObject()
        Object object = in.readObject();
        System.out.println(object);
        // close
        in.close();

    }

    private void writeObj() throws IOException {
        // 创建输出流对象
        ObjectOutputStream out =
                new ObjectOutputStream(new FileOutputStream("b.txt"));

        // 创建1个学生对象
        Student student = new Student("张三", 20);
        // writeObject(Object o)
        out.writeObject(student);

        // close
        out.close();
    }

注意事项

  • Serializable是1个空接口,起到标记作用
  • java.io.NotSerializableException 没有实现Serializable接口
  • java.io.InvalidClassException: com.cskaoyan._02otherstream.Student; local class incompatible: stream classdesc serialVersionUID = -6179896537945312425, local class serialVersionUID = 8703206464746270080
  • transient 用来修饰不想被序列化的成员变量

总结

类型字节输出流字节输入流字符输出流字符输入流
抽象基类OutputStreamInputStreamWriterReader
文件相关FileOutputStreamFileInputStreamFileWriterFileReader
缓冲相关BufferedOutputStreamBufferedInputStreamBufferedWriterBufferedReader
转换想关OutputStreamWriterInputStreamReader
数据相关DataOutputStreamDataInputStream
打印相关PrintStreamPrintWriter
对象相关ObjectOutputStreamObjectInputStream
这篇关于Java--IO的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!