java基础之io的理解与应用

 

一、File类

File类概述和构造方法

  • File类介绍

    • 它是文件和文件夹 路径名的抽象表示

    • 对于File而言,其封装的并不是一个真正存在的文件或者文件夹,仅仅是一个路径名而已.它可以是存在的,也可以是不存在的.

  • File类的构造方法

716b28b7c77940128078c2ad2224aa64.png

public class FileDemo1 {
    public static void main(String[] args) {
        //File(String pathname)    通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
        // method1();

        //File(String parent, String child)    从父路径名字符串和子路径名字符串创建新的File实例
        // method2();

        //File(File parent, String child)      从父抽象路径名和子路径名字符串创建新的File实例
        method3();
    }

    private static void method3() {
        //File(File parent, String child)      从父抽象路径名和子路径名字符串创建新的File实例
        File file1 = new File("D:\\itheima");
        String path = "a.txt";
        File file = new File(file1,path);
        System.out.println(file);//D:\itheima\a.txt
    }

    private static void method2() {
        //File(String parent, String child)    从父路径名字符串和子路径名字符串创建新的File实例
        String path1 = "D:\\itheima";
        String path2 = "a.txt";
        File file = new File(path1,path2);//把两个路径拼接.
        System.out.println(file);//D:\itheima\a.txt
    }

    private static void method1() {
        //File(String pathname)        通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
        String path = "D:\\itheima\\a.txt";
        File file = new File(path);
        System.out.println(file);//D:\itheima\a.txt
        //问题:为什么要把字符串表示形式的路径变成File对象?
        //就是为了使用File类里面的方法.
    }
}

绝对路径和相对路径

  • 绝对路径

    是一个完整的路径,从盘符开始

  • 相对路径

    是一个简化的路径,相对当前项目下的路径

  • 示例代码

public class FileDemo2 {
    public static void main(String[] args) throws IOException {
        //这个路径固定不变了.
        File file = new File("D:\\itheima\\a.txt");
        // file.createNewFile();

        //当前项目下的a.txt
        //AdvancedCode\a.txt
        File file2 = new File("a.txt");
        // file2.createNewFile();

        //当前项目下 --- 指定模块下的 a.txt 
        File file3 = new File("day12-file\\a.txt");
        file3.createNewFile();
    }
}

File类创建功能

e4942b95d04c4ae7bafdd51c9fe18f63.png

public class FileDemo3 {
    public static void main(String[] args) throws IOException {
        //public boolean createNewFile()    创建一个新的空的文件
        //注意:
            //1.如果文件存在,那么创建失败,返回false
            //2.如果文件不存在,那么创建成功,返回true
            //3.createNewFile方法只能创建文件,建议加上文件后缀名。
        // method1();

        //public boolean mkdir()            创建一个单级文件夹
        //注意: 只能创建单级文件夹,不能创建多级文件夹
        // method2();

        //public boolean mkdirs()           创建一个多级文件夹
        //注意: 可以创建单级文件夹,也可以创建多级文件夹
        method3();
    }

    private static void method3() {
        // File file = new File("D:\\itheima\\aaa");
        File file = new File("D:\\itheima\\aaa\\bbb\\ccc");
        boolean result = file.mkdirs(); // 创建文件夹
        System.out.println(result);
    }

    private static void method2() {
        File file = new File("D:\\itheima\\aaa\\bbb");
        boolean result = file.mkdir();
        System.out.println(result);
    }

    private static void method1() throws IOException {
        File file1 = new File("D:\\itheima\\a");
        boolean result1 = file1.createNewFile();
        System.out.println(result1);
    }
}

File类删除功能

public class FileDemo4 {
    //注意点:
        //1.不走回收站的.
        //2.如果删除的是文件,那么直接删除.如果删除的是文件夹,那么只能删除空文件夹
        //3.如果要删除一个有内容的文件夹,只能先进入到这个文件夹,把里面的内容全部删除完毕,才能再次删除这个文件夹
    //简单来说:
        //只能删除文件和空文件夹.
    public static void main(String[] args) {
        method1();

        File file = new File("D:\\itheima");
        boolean result = file.delete();
        System.out.println(result);
    }

    private static void method1() {
        File file = new File("D:\\itheima\\a.txt");
        boolean result = file.delete();
        System.out.println(result);
    }
}

File类判断和获取功能

867d945875c04381a8a877cfb3b4d7b2.png

public class FileDemo5 {
    public static void main(String[] args) {
        //public boolean isDirectory()  测试此抽象路径名表示的File是否为目录
        //public boolean isFile()       测试此抽象路径名表示的File是否为文件
        // method1();
        // method2();

        //public boolean exists()       测试此抽象路径名表示的File是否存在
        // method3();

        //public String getName()       返回由此抽象路径名表示的文件或目录的名称
        //注意:
            //1.如果调用者是文件,那么获取的是文件名和后缀名
            //2.如果调用者是一个文件夹,那么获取的是文件夹的名字
        method4();
    }

    private static void method4() {
        File file = new File("b.txt");
        String name = file.getName();   // 获取名称
        System.out.println(name);

        File file1 = new File("D:\\demo");
        String name2 = file1.getName();   // 获取名称
        System.out.println(name2);
    }

    private static void method3() {
        File file = new File("D:\\itheima\\a.txt");
        boolean result = file.exists();  // 判断路径是否存在
        System.out.println(result);
    }

    private static void method2() {
        File file = new File("D:\\itheima");
        boolean result1 = file.isFile();   // 判断是否是文件
        boolean result2 = file.isDirectory();   // 判断是否是文件夹
        System.out.println(result1);
        System.out.println(result2);
    }

    private static void method1() {
        File file = new File("D:\\itheima\\a.txt");
        boolean result1 = file.isFile();
        boolean result2 = file.isDirectory();
        System.out.println(result1);
        System.out.println(result2);
    }
}	
public class FileDemo6 {
    public static void main(String[] args) {
        File file = new File("D:\\itheima");

        File[] files = file.listFiles();//返回值是一个File类型的数组

        System.out.println(files.length);

        if(files != null) {
            for (File path : files) {
                System.out.println(path);
            }
        }

        //进入文件夹,获取这个文件夹里面所有的文件和文件夹的File对象,并把这些File对象都放在一个数组中返回.
        //包括隐藏文件和隐藏文件夹都可以获取.
        //注意事项:
        //1.当调用者是一个文件时,返回null。
        //2,当调用者是一个空文件夹时,返回的数组长度为0.
        //3.当调用者是一个有内容的文件夹时,返回所有内容的File对象数组。
        //4.当调用者是一个有权限才能进入的文件夹时,返回null。
    }
}

二、字节流​

IO流概述和分类

  • IO流介绍

    • 用来对文件内容进行读和取,实现持久化存储。读和取(输入和输出)  以我们写的程序为基准。

  • IO流的分类

    • 字节流

    • 字符流

    • 字节输入流

    • 字节输出流

    • 字符输入流

    • 字符输出流

    • 输入流:读数据

    • 输出流:写数据

    • 按照数据的流向

    • 按照数据类型来分

  • IO流的使用场景

    • 如果操作的是纯文本文件,优先使用字符流

      纯文本文件:用记事本能打开并能看懂的文件。

    • 如果操作的是图片、视频、音频等二进制文件,使用字节流

    • 如果不确定文件类型,优先使用字节流.字节流是万能的流

字节流写数据

  • 字节流抽象基类

    • InputStream:这个抽象类是表示字节输入流的所有类的超类

    • OutputStream:这个抽象类是表示字节输出流的所有类的超类

    • 子类名特点:子类名称都是以其父类名作为子类名的后缀

  • 字节输出流

    • FileOutputStream(String name):创建文件输出流以指定的名称写入文件

d11b019b743d4c6dbcf175db2f164be7.png

  • 使用字节输出流写数据的步骤

    • 创建字节输出流对象

      如果文件不存在,则创建,如果存在,则默认清空,可以在对象创建时指定是否追加。

    • 写数据

      写出的整数,实际写出的是该整数在码表上对应的字符。

    • 释放资源

      不释放资源,相当于文件还被占用,无法删除。

  • 示例代码

public class OutputDemo1 {
    public static void main(String[] args) throws IOException {
        //1.创建字节输出流的对象 --- 告诉虚拟机我要往哪个文件中写数据了
        FileOutputStream fos = new FileOutputStream("D:\\a.txt");
        //FileOutputStream fos = new FileOutputStream(new File("D:\\a.txt"));
        //2,写数据
        fos.write(97);
        //3,释放资源
        fos.close();
    }
}

public class OutputDemo2 {
    public static void main(String[] args) throws IOException {
        //1.创建字节输出流的对象
        //注意:如果文件不存在,会帮我们自动创建出来.
        //如果文件存在,会把文件清空.
        FileOutputStream fos = new FileOutputStream("D:\\demo\\a.txt");
        //2,写数据  传递一个整数时,那么实际上写到文件中的,是这个整数在码表中对应的那个字符.
        fos.write(98);
        //3,释放资源
        fos.close(); //告诉操作系统,我现在已经不要再用这个文件了.
    }
}

字节流写数据的三种方式

ba2ac1f825a041d08537dd893b8c364e.png

public class OutputDemo4 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("D:\\a.txt");
        //一次写一个字节数据
        /*fos.write(97);
        fos.write(98);
        fos.write(99);*/

        //一次写一个字节数组数据
        /*byte [] bys = {97,98,99};
        fos.write(bys);*/

        //一次写一个字节数组一部分数据
        byte [] bys = {97,98,99,100,101,102,103};
        fos.write(bys,1,2);

        //释放资源
        fos.close();
    }
}

字节流写数据的两个小问题

  • 字节流写数据如何实现换行

    • windows:\r\n

    • linux:\n

    • mac:\r

  • 字节流写数据如何实现追加写入

    • public FileOutputStream(String name,boolean append)

    • 创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头

  • 示例代码

public class OutputDemo5 {
    public static void main(String[] args) throws IOException {
        //第二个参数就是续写开关,如果没有传递,默认就是false,
        //表示不打开续写功能,那么创建对象的这行代码会清空文件.
        //如果第二个参数为true,表示打开续写功能
        //那么创建对象的这行代码不会清空文件.
        FileOutputStream fos = new FileOutputStream("D:\\demo\\a.txt",true);

        fos.write(97);
        //能加一个换行
        fos.write("\r\n".getBytes());
        fos.write(98);
        //能加一个换行
        fos.write("\r\n".getBytes());
        fos.write(99);

        fos.close();
    }
}

 字节流读数据(一次读一个字节数据)

 

  • 字节输入流

    • FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名

  • 字节输入流读取数据的步骤

    • 创建字节输入流对象

    • 调用字节输入流对象的读数据方法

    • 释放资源

  • 示例代码

public class InputDemo7 {
    public static void main(String[] args) throws IOException {
        //如果文件存在,那么就不会报错.
        //如果文件不存在,那么就直接报错.
        FileInputStream fis = new FileInputStream("D:\\a.txt");
​
        //一次读取一个字节,返回值就是本次读到的那个字节数据.
        //也就是字符在码表中对应的那个数字.
        int read = fis.read();
​
        //如果我们想要看到的是字符数据,那么一定要强转成char
        System.out.println((char)read);
​
        //释放资源
        fis.close();
​
    }
}
​
public class InputDemo8 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("day12-ByteStream\\a.txt");
​
        //b用于记录每次读到的字节数据
        int b;
​
        /*
            fis.read()  一次读取一个字节数据
            (b = fis.read())   将读取到的字节数据赋值给b
            (b = fis.read()) != -1    判断是否读取到了文件的末尾
         */
        while((b = fis.read()) != -1){
            System.out.print((char) b);
        }
​
        fis.close();
    }
}

字节流读数据(一次读一个字节数组数据)

  • 一次读一个字节数组的方法

    • public int read(byte[] b):从输入流读取最多b.length个字节的数据

    • 返回的是读入缓冲区的总字节数,也就是实际的读取字节个数

  • 示例代码

public class FileCopyDemo10 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("D:\\itheima\\a.avi");
        FileOutputStream fos = new FileOutputStream("D:\\itheima\\b.avi");

        byte[] bytes = new byte[1024];
        int len;//本次读到的有效字节个数 --- 这次读了几个字节

        while((len = fis.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }

        fis.close();
        fos.close();
    }
}

字节流复制文件原理

643d1031276c479f8ee27c711773fa54.png

三、字节缓冲流

字节缓冲流构造方法

  • 字节缓冲流介绍

    • BufferOutputStream:缓冲字节输出流

    • BufferedInputStream:缓冲字节输入流

  • 构造方法:

public class BufferedDemo11 {
    public static void main(String[] args) throws IOException {
        //利用字节缓冲流去拷贝文件
        //创建一个字节缓冲输入流
        //在底层创建了一个默认长度为8192的字节数组。
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\itheima\\a.avi"));
        //创建一个字节缓冲输出流
        //在底层也创建了一个默认长度为8192的字节数组。
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\itheima\\b.avi"));

        int b;
        while((b = bis.read()) != -1){
            bos.write(b);
        }

        //方法的底层会把字节流给关闭。
        bis.close();
        bos.close();
    }
}

字节缓冲流复制文件

  • 案例需求

    把“D:\itheima\a.avi”复制到模块目录下的“a.avi”

  • 实现步骤

    • 根据数据源创建字节输入流对象

    • 根据目的地创建字节输出流对象

    • 读写数据,复制视频

    • 释放资源

  • 代码实现

public class BufferedDemo12 {
    public static void main(String[] args) throws IOException {
        //创建一个字节缓冲输入流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\itheima\\a.avi"));
        //创建一个字节缓冲输出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\itheima\\b.avi"));

        //以数组形式
        byte[] bytes = new byte[1024];
        int len;
        while((len = bis.read(bytes)) != -1){
            bos.write(bytes,0,len);
        }

        bis.close();
        bos.close();
    }
}

字节缓冲流复制文件原理

字节缓冲流复制文件原理

        缓冲流帮我们减少了硬盘和内存之间的IO次数,再通过字节数组可以帮助我们减少内存之间拷贝的次数。所以我们平时使用的时候通常用缓冲流并以字节数组的形式来进行读写操作。

07d413c6ea5a44b4b3915b0a5357534b.png

 

 

四、字符流

  • 字符流的介绍

    由于字节流操作中文不是特别的方便,所以Java就提供字符流

    字符流 = 字节流 + 编码表

  • 中文的字节存储方式

    用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文,如何识别是中文的呢?

    汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数

  • 代码演示

public class CharStreamDemo1 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("D:\\itheima\\a.txt");
        int b ;
        while((b = fis.read()) != -1){
            System.out.println((char) b);
        }
        fis.close();
    }
}

 

字符流写数据

  • 介绍

    Writer: 用于输入字符流的抽象父类

    FileWriter: 用于输入字符流的常用子类

  • ​构造方法

349d83beb7734c1a8a216bd5f957daee.png

 

public class CharStreamDemo3 {
    public static void main(String[] args) throws IOException {
        //创建字符输出流的对象
        //FileWriter fw = new FileWriter(new File("day13-CharStream\\a.txt"));
        FileWriter fw = new FileWriter("day13-CharStream\\a.txt");

        /*//写出数据
        //void write(int c)            写一个字符
        fw.write(97);
        fw.write(98);
        fw.write(99);*/
        // fw.write('你');

        //void write(char[] cbuf)      写出一个字符数组
       /* char [] chars = {97,98,99,100,101};
        fw.write(chars);*/

        //void write(char[] cbuf, int off, int len)    写出字符数组的一部分
        /*char [] chars = {97,98,99,100,101};
        fw.write(chars,0,3);*/

        //void write(String str)       写一个字符串
        String line = "黑马程序员abc";
        fw.write(line);

        //void write(String str, int off, int len)     写一个字符串的一部分
        /*String line = "黑马程序员abc";
        fw.write(line,0,2);*/

        //释放资源
        fw.close();
    }
}

字符缓冲流

  • 字符缓冲流介绍

    • BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途

    • BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途

  • 构造方法

48ee1b0945604f8c833c5a6eef4680e9.png

public class BufferedStreamDemo01 {
    public static void main(String[] args) throws IOException {
        //BufferedWriter(Writer out)
        BufferedWriter bw = new BufferedWriter(new                                                            FileWriter("myCharStream\\bw.txt"));
        bw.write("hello\r\n");
        bw.write("world\r\n");
        bw.close();

        //BufferedReader(Reader in)
        BufferedReader br = new BufferedReader(new                                                           FileReader("myCharStream\\bw.txt"));

        //一次读取一个字符数据
//        int ch;
//        while ((ch=br.read())!=-1) {
//            System.out.print((char)ch);
//        }

        //一次读取一个字符数组数据
        char[] chs = new char[1024];
        int len;
        while ((len=br.read(chs))!=-1) {
            System.out.print(new String(chs,0,len));
        }

        br.close();
    }
}

字符缓冲流特有功能

9626d8aea5384859940dd83f09904f70.png

public class CharStreamDemo11 {
    public static void main(String[] args) throws IOException {
        //字符缓冲流的特有功能
        //字符缓冲输出流BufferedWrite : newLine()  跨平台的换行符

        //创建对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("day13-CharStream\\a.txt"));

        //写出数据
        bw.write("黑马程序员666");
        //跨平台的回车换行
        bw.newLine();
        bw.write("abcdef");
        //跨平台的回车换行
        bw.newLine();
        bw.write("-------------");

        //刷新流
        bw.flush();
        //释放资源
        bw.close();
    }
}

总结:

bba48213f18c4c0c99191e441eaae1ba.png

 

五、转换流

字符流中和编码解码问题相关的两个类

  • InputStreamReader:是从字节流到字符流的桥梁,父类是Reader

    它读取字节,并使用指定的编码将其解码为字符

    它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集

  • OutputStreamWriter:是从字符流到字节流的桥梁,父类是Writer

    是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节

    它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集

转换流读写数据

73377f9de75745abb4f3b74b274731bf.png

public class ConvertedDemo1 {
    public static void main(String[] args) throws IOException {
        // method1();
        // method2();
        // method3();
    }

    private static void method3() throws IOException {
        //在JDK11之后,字符流新推出了一个构造,也可以指定编码表
        FileReader fr = new FileReader("D:\\itheima\\convert.txt", Charset.forName("gbk"));
        int ch;
        while ((ch = fr.read()) != -1) {
            System.out.println((char) ch);
        }
        fr.close();
    }

    private static void method2() throws IOException {
        //如何解决乱码现象
        //文件是什么码表,那么咱们就必须使用什么码表去读取.
        //我们就要指定使用GBK码表去读取文件.
        InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\itheima\\convert.txt"), "gbk");
        int ch;
        while ((ch = isr.read()) != -1) {
            System.out.println((char) ch);
        }
        isr.close();

        //按照指定的编码格式写出数据到文件
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\itheima\\b.txt"), "utf-8");
        osw.write("我爱学习,谁也别打扰我");
        osw.close();
    }

    //这个方法直接读取会产生乱码
    //因为文件是GBK码表
    //而idea默认的是UTF-8编码格式.
    //所以两者不一致,导致乱码
    private static void method1() throws IOException {
        FileReader fr = new FileReader("D:\\itheima\\convert.txt");
        int ch;
        while ((ch = fr.read()) != -1) {
            System.out.println((char) ch);
        }
        fr.close();
    }
}

对象操作流

对象序列化流【应用】

  • 对象序列化介绍

    • 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象

    • 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息

    • 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息

    • 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

  • 对象序列化流: ObjectOutputStream

    • 将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象

  • 构造方法

4b6c317351294abcacba4ea1c44d0a19.png

 

public class Student implements Serializable {
    private String name;
    private int age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class ConvertedDemo3 {
    public static void main(String[] args) throws IOException {
        //类必须实现Serializable接口,才能参与序列化操作
        User user = new User("zhangsan","qwer");

        //创建对象输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day13-OtherIO\\a.txt"));
        //写出对象
        oos.writeObject(user);
        //释放资源
        oos.close();
    }
}

对象反序列化流

  • 对象反序列化流: ObjectInputStream

    • ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象

  • 构造方法

986bd3c4a210456da4353db864c0d4ee.png

public class ConvertedDemo4 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创建对象输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day13-OtherIO\\a.txt"));
        //读取对象
        User u = (User) ois.readObject();
        //操作
        System.out.println(u);
        //释放资源
        ois.close();
    }
}

 

 

 

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值