Java IO 流

目录

1. File类

        1.1 介绍

        1.2 创建文件对象

        1.3 常用的文件操作 

 2. IO 流原理及流分类

        2.1 IO 流原理

        2.2 流的分类

 3. 常用的类

        3.1 FileInputStream 和 FileOutStream

        3.2 FileReader 和 FileWriter

4. 处理流 

5. 处理流常用类

        5.1 缓冲流

        5.2 对象流

        5.3 转换流

        5.4 打印流


1. File类

        1.1 介绍

        Java文件类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。

        1.2 创建文件对象

        创建文件的对象既可以时一个确切的文件(.txt、.doc、.word 等文件),也可以是目录(d:/aaa/bbb/ccc)。

        //1. 通过给定的父抽象路径名和子路径名字符串创建一个新的File实例。
        //File(File parent, String child);
        File file1 = new File(new File("d:/temp"),"aaa/a.txt");

        //2. 通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例。
        //File(String pathname)
        File file2 = new File("d:/temp/aaa/a.txt");

        //3.根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
        //File(String parent, String child)
        File file3 = new File("d:/temp/aaa", "bbb/a.txt");

        //4. 通过将给定的 file: URI 转换成一个抽象路径名来创建一个新的 File 实例。
        //File(URI uri)
        File file4 = new File(new URI("file:/d:/temp/a.txt"));
        

        1.3 常用的文件操作 

        File file1 = new File("d:/AAA/aaa.txt");  //创建file对象
        file1.createNewFile(); // 创建文件

        File file2 = new File("d:/AAA/bbb");
        file2.mkdir(); //创建单级目录
        file2.deleteOnExit(); //程序退出时删除

        File file3 = new File("d:/AAA/ccc/ddd");
        file3.mkdirs();//创建多级目录
        file3.delete();//删除

        //先创建文件对象
        File file = new File("d:/AAA/a.txt");
        //调用相应的方法,得到对应信息
        System.out.println("文件名字=" + file.getName());
        //getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory
        System.out.println("文件绝对路径=" + file.getAbsolutePath());
        System.out.println("文件父级目录=" + file.getParent());
        System.out.println("文件大小(字节)=" + file.length());
        System.out.println("文件是否存在=" + file.exists());
        System.out.println("是不是一个文件=" + file.isFile());
        System.out.println("是不是一个目录=" + file.isDirectory());

 2. IO 流原理及流分类

        2.1 IO 流原理

        Java程序中,对于数据的输入/输出操作都是以“流(Stream)”的方式进行,I / O 是 Input / Output 的缩写,是非常实用的技术,用于处理数据传输,如读 / 写 文件,网络通讯等。(输入和输出相对程序来说,输入是把程序外的数据读入到程序中,输出是把数据从程序写出到指定位置

        Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。Java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。

        2.2 流的分类

        1. 按操作的数据单位不同分为:字节流(8 bit)二进制文件,字符流(按字符)文本文件

         使用前须知:由于字节流是一个字节一个字节的读取,utf-8编码中一个英文字符占用一个字节,因此使用字节流读取英文文件不会出现乱码,但是中文占用3个字节,所以可能出现乱码,又因为用字符流操作二进制文件可能会造成文件损坏,因此一般对于文本文件使用字符流操作,对于字节流文件(音频,视频)使用字节流操作

        2. 按数据流的流向不同分为:输入流/输出流

        3. 按流的角色不同分为: 节点流,处理流(包装流)

 3. 常用的类

        3.1 FileInputStream 和 FileOutStream

        //创建FileInputStream对象
        FileInputStream fileInputStream = new FileInputStream("d:/temp/a.txt");
        //字节数组用与存储数据
        byte[] bytes = new byte[8]; //数组长度可指定
        //记录每次读取的实际长度
        int readlen = 0;
        //对文件循环读取 read(),会返回一个数字表示读取的长度,如果没有返回-1
        while((readlen = fileInputStream.read(bytes)) != -1){
            //以字符串的形式输出到控制台
            //实际读取多少就输出多少,readlen 为实际读取长度
            //如果没有控制长度的readlen 有可能会错误
            //假设文本里面的数据为 Hello, world!
            //而你顶的数组长度为[5]
            //第一次读取['H','e','l','l','o']
            //第二次读取[',','w','o','r','l']
            //第三次读取后数组变为:['d','!','o','r','l']
            //因为第三次就读取了两个 'd' 和 '!',所以后面的数据不会改变
            //如果没有确定实际读取长度,那么后面的也会输出
            //后面不在解释
            System.out.print(new String(bytes,0,readlen));
        }
        //关闭流
        fileInputStream.close();
        FileOutputStream fileOutputStream = new FileOutputStream("d:/temp/b.txt");
        String s = "Hello, lcy!";
        fileOutputStream.write(s.getBytes(),0,s.getBytes().length);
        fileOutputStream.close();
        //FileInputStream与FileOutputStream结合实现音频文件拷贝       
        FileInputStream fileInputStream = new FileInputStream("d:/temp/CelloFox.flac");
        FileOutputStream fileOutputStream = new FileOutputStream("d:/temp/CelloFox2.flac");
        byte[] buf = new byte[1024];
        int readlen = 0;
        while((readlen = fileInputStream.read(buf)) != -1){
            fileOutputStream.write(buf,0,readlen);
        }
        fileInputStream.close();
        fileOutputStream.close();

        3.2 FileReader 和 FileWriter

        //创建 FileReader 对象
        FileReader fileReader = new FileReader("d:/temp/a.txt");
        //使用 char 数组 存储读取的数据
        char[] chars = new char[8];
        //记录实际读取的长度
        int readline = 0;
        //对文本进行读取
        while((readline = fileReader.read(chars)) != -1){
            System.out.print(new String(chars, 0, readline));
        }
        fileReader.close();
        //创建 FileWriter 对象
        //public FileWriter(String fileName, boolean append) 
        //后面带有boolean 时,true代表追加,false 代表重新写入,原先的数据将会被覆盖
        FileWriter fileWriter = new FileWriter("d:/temp/c.txt", true);
        //直接使用 write() 写入
        fileWriter.write("Hello, world");
        //记得关闭流
        fileWriter.close();
        FileReader fileReader = new FileReader("d:/temp/a.txt");
        FileWriter fileWriter = new FileWriter("d:/temp/f.txt");
        char[] chars = new char[8];
        //实际读取长度
        int readlen = 0;
        while((readlen = fileReader.read(chars)) != -1){
            //读取后直接以字符串的形式写入
            fileWriter.write(new String(chars,0,readlen));
        }
        fileReader.close();
        fileWriter.close();

4. 处理流 

        根据流的角色分为 节点流 处理流,之前使用的都是节点流,现在介绍处理流:

        处理流也叫包装流,是在已存在的流之上,为程序提供更强大的读写能力,也更加灵活

(性能提高,操作便捷)

         节点流 和 处理流的区别和联系:

        1. 节点流 是底层流,直接跟数据源相接

        2. 处理流 包装 节点流,既可以消除不同节点流的实现差异,也可提供更方便的方法完成输入输出

        3. 处理流 使用了修饰器设计模式,不会直接与数据源项链

5. 处理流常用类

        5.1 缓冲流

        字符缓冲流:BufferedReader 和 BufferedWriter

        BufferedReader bufferedReader = new BufferedReader(new FileReader("d:/temp/a.txt"));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("d:/temp/a1.txt"));
        char[] chars = new char[8];
        int readlen = 0;
        while((readlen = bufferedReader.read(chars)) != -1){
            bufferedWriter.write(chars, 0, readlen);
        }
        bufferedReader.close();
        bufferedWriter.close();

        字节缓冲流:BufferedInputStream 和 BufferedOutputStream

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:/temp/CelloFox.flac"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:/temp/CelloFox1.flac"));
        byte[] bytes = new byte[1024];
        int readlen = 0;
        while((readlen = bis.read(bytes)) != -1){
            bos.write(bytes, 0, readlen);
        }
        bis.close();
        bos.close();

        5.2 对象流

        对象流能够在保存数据的同时把数据的类型保存下来,比如保存 int 100,那么不仅仅保存了100这个数据,同时保存了 它的类型:int,再比如保存一个对象 Student s = new Student("小红", 18),那么在恢复时便知道是一个 Student 类型。

        使用须知: 如果想把数据类型进行保存,那么这个数据类型需实现序列化

        序列化 : 保存数据时,保存数据的值和数据类型

        反序列化:恢复数据时,恢复数据的值和数据类型

        如果需让某个对象能够支持序列化机制,必须让其类实现Serializable(此接口没有方法需实现类实现,常用) 或者 Externalizable

        //序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
        String filePath = "e:\\data.dat";
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
        //序列化数据到 e:\data.dat
        oos.writeInt(100);// int -> Integer (实现了 Serializable)
        oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)
        oos.writeChar('a');// char -> Character (实现了 Serializable)
        oos.writeDouble(9.5);// double -> Double (实现了 Serializable)
        oos.writeUTF("lcy");//String
        //保存一个 dog 对象
        oos.writeObject(new Dog("旺财", 10, "日本", "白色"));
        oos.close();
        System.out.println("数据保存完毕(序列化形式)");
        // 1.创建流对象 对上面存储的数据进行读取
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src\\data.dat"));
        // 2.读取, 注意顺序
        System.out.println(ois.readInt());
        System.out.println(ois.readBoolean());
        System.out.println(ois.readChar());
        System.out.println(ois.readDouble());
        System.out.println(ois.readUTF());
        System.out.println(ois.readObject());
        System.out.println(ois.readObject());
        System.out.println(ois.readObject());
        // 3.关闭
        ois.close();
        System.out.println("以反序列化的方式读取(恢复)ok~");

          注意:序列化对象时,默认里面的属性都要进行序列化(除了static 和 transient 修饰的成员),要求里面的属性也要实现序列化接口,序列化具备可继承性,某类实现了序列化,则他的子类默认实现了序列化。

        5.3 转换流

        InputStreamReader 和 OutputStreamWriter

        1. InputStreamReader 是 Reader 的子类,可以将 InputStream 转换成 Reader

        2. OutputStreamWriter 是 Writer 的子类,可以将 OutputStream 转换成Writer

        3. 可以在使用转换流是指定编码格式(按照什么格式输入/按照什么格式输入(utf-8,gbk等))

        String filePath = "d:/temp/a.txt";
        //解读
        //1. 把 FileInputStream 转成 InputStreamReader

        //2. 指定编码 gbk
        //InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
        //3. 把 InputStreamReader 传入 BufferedReader
        //BufferedReader br = new BufferedReader(isr);

        //将 2 和 3 合在一起
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "gbk"));
        //4. 读取
        String s = br.readLine();
        System.out.println("读取内容=" + s);
        //5. 关闭外层流
        br.close();

        // 1.创建流对象
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:/temp/a.txt"), "gbk");
        // 2.写入
        osw.write("hello,lcy~");
        // 3.关闭
        osw.close();
        System.out.println("保存成功~");

        5.4 打印流

        PrintStream 和 PrintWriter  打印流只有输出流,没有输入流

        PrintStream out = System.out;
        //在默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器
        /*
        public void print(String s) {
            if (s == null) {
                s = "null";
            }
            write(s);
        }
        */
        out.print("lcy, hello");
        System.out.println();
        //因为 print 底层使用的是 write , 所以我们可以直接调用 write 进行打印/输出
        out.write("lcy,你好".getBytes());
        System.out.println();
        out.close();
        //我们可以去修改打印流输出的位置/设备
        //1. 输出修改成到 "d:/temp/a.txt"
        //2. "lcy, hello" 就会输出到 d:/temp/a.txt
        //3. public static void setOut(PrintStream out) {
        //      checkIO();
        //      setOut0(out); // native 方法,修改了 out
        //  }
        System.setOut(new PrintStream("e:\\f1.txt"));
        System.out.println("hello, lcy");
        System.out.println();

        //PrintWriter 的使用
        //PrintWriter printWriter = new PrintWriter(System.out);
        PrintWriter printWriter = new PrintWriter(new FileWriter("e:\\f2.txt"));
        printWriter.print("hi, lcy");
        System.out.println();
        printWriter.close(); //flush + 关闭流, 才会将数据写入到文件

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱喝可乐的灵麟鲤

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

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

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

打赏作者

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

抵扣说明:

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

余额充值