十一、IO流

1. File类

1.1 File类简介

        File 类 就是当前系统中 文件或者文件夹的抽象表示。通俗的讲 就是 使用File对象 才操作我们电脑系统中的文件或者文件夹。学习File类 其实就是学习 如果通过file对象 对系统中的文件/文件夹进行增删改查。

1.2 创建File对象

1 前期准备
    在电脑的非系统盘 创建一个 test文件夹 今天所有的操作都在这个文件夹中

2 创建

 public void test() {

        /*  path 路径
          Creates a new <code>File</code> instance by converting the given
          pathname string into an abstract pathname.  If the given string is
          the empty string, then the result is the empty abstract pathname
          File(String) 参数为String类型的目标文件路径名
         */
        File file = new File("D:\\aaa\\123.txt");

        /*  路径分割符
         *  D:\haha\hehe\123.mp4    称之为路径  其中 \ 就是路径分割符 代表的是 下级目录
         *  在windows系统中 路径分割符为  \   在 Linux 和 Mac 中 路径分割符是 /
         *  我们写的java代码  需要跨平台 多环境运行   开发环境:windows   生成环境:Linux
         *  此时就会出现一个问题  如果我们的路径分隔符 写成 \  在 windows中好使 到了 Linux就不识别
         *  所以我们可以使用以下两种方式解决:
         *
         * */
        /* 方式1 :  windows不仅支持 \ 还支持/ */
        File file1 = new File("D:/aaa/123.txt");

        /* 方式2:   使用动态识别的常量  */
        // ;
        System.out.println(File.pathSeparator);
        // \ 
        System.out.println(File.separator);
       
        File file2 = new File("D:" + File.separator + "aaa" + File.separator + "123.txt");
    }

1.3 增加操作

        1 创建新的文件  2 创建新的文件夹

public class Test1 {
    public static void main(String[] args) throws IOException {
        File file = new File("E:/aaa666/a.txt");//创建文件
        file.createNewFile();
        File file1 = new File("E:/aaa666/aaa");//使根据你调用得方法不同 而创建不同得类型
        file1.createNewFile();
        File file2 = new File("E:/aaa666/b");//创建目录
        file2.mkdir();
        File file3 = new File("E:/aaa666/c/cc/ccc");//创建多层目录
        file3.mkdirs();
    }
}

1.4 删除操作

public class Test {
    public static void main(String[] args) throws InterruptedException {
        File file = new File("E:/aaa666/a.txt");//删除文件
        file.delete();
        File file1 = new File("E:/aaa666/b");//当程序退出后 删除
        file.deleteOnExit();
        Thread.sleep(2000);//让程序休眠2秒
        File file2 = new File("E:/aaa666/j");//删除空目录
        file2.delete();
    }
}

注意:删除目录,必须是空目录的情况下才能使用delete方法进行删除。

1.5 修改操作

public static void main(String[] args) throws IOException {
    File file=new File("D:/AAA/c.txt");
    file.createNewFile();
    file.setReadable(false);//设置该文件得权限为不能读
    file.setWritable(false);//设置该文件不能写
    file.setReadOnly();//设置只读得权限
    file.renameTo(new File("D:/AAA/d.txt"));//重命名
} 

1.6 查询操作

public class Test1 {
    public static void main(String[] args) {
       File file = new File("E:/aaa666/a.txt");
        String name = file.getName();//得到文件得名称
        System.out.println(name);
        String parent = file.getParent();//得到父级路径得名称
        System.out.println(parent);
        String path = file.getPath();//得到文件得路径名称
        System.out.println(path);
        boolean directory = file.isDirectory(); //判断该文件对象是否为目录类型
        System.out.println(directory);
        boolean file1 = file.isFile();//判断该文件对象是否为文件类型
        System.out.println(file1);
        File file2 = new File("E:/aaa666");
        String[] list = file2.list();//列出AAA目录下所有子文件得名称
        System.out.println(Arrays.toString(list));//列出AAA目录下所有文件对象
        File[] files = file2.listFiles();
        //遍历输出
        for (File a:files){
         System.out.println(a.toString());
        }
    }
}

        下面讲一个经典的面试题:通过递归的方法,输出指定目录下的所有文件。话不多说我们直接上代码:

public class Test1 {
    public static void main(String[] args) {
        showAllFiles("E:/aaa666");
    }
    public static void showAllFiles(String path){
        File file = new File(path);
        if (!file.exists() || !file.isDirectory()){
            return;
        }
        File[] files = file.listFiles();
        for (File a:files){
            if (a.isDirectory()) {
                showAllFiles(a.getPath());
            }else {
                System.out.println(a.getPath());
            }
        }
    }
}

2. IO流

2.1 IO流概述

IO都是全大写 说明肯定是两个单词的首字母
I   inputstream 输入流     O  outputstream  输出流
IO 称之为 java的输入输出流
其实学习IO  就是学习  如何通过java代码 对文件内容 进行   读(输入流)  写(输出流)
所以有一话:   读进来 写出去。

Java流的分类
按流向分:
输入流: 程序可以从中读取数据的流。
输出流: 程序能向其中写入数据的流。
     
按数据传输单位分:
字节流: 以字节为单位传输数据的流
字符流: 以字符为单位传输数据的流
     
按功能分:
节点流: 用于直接操作目标设备的流       ----  四大基流
过滤流: 是对一个已存在流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。    ----  包装流  
 
  
四大基流: 字节输入流    字节输出流   字符输入流   字符输出流


       
       
    这里面我们主要学习:FileWriter(文件输出字符流)、FileReader(文件输入字符流)、ObjectOutputStream(对象输出字节流)、FileOutputStream(文件输出字节流)、BufferedOutputStream(缓冲输出字节流)、ObjectInputStream(对象输入字节流)、FileInputStream(文件输入字节流)、BufferedInputStream(缓冲输入字节流)。

2.2 Writer字符输出流

它是所有字符输出流的父类。---FileWriter类

public class Test1 {
    public static void main(String[] args) throws IOException {
        Writer writer = new FileWriter("E:/aaa666/a.txt");
        String str = "今天代码真的多";
        writer.write(str);
        writer.flush();//刷新流
        writer.close();//关闭流资源


//上面每次往文件中写内容时 就会把原来的内容覆盖了。如何追加内容:
        //true:表示允许追加内容到文件中
        Writer writer1 = new FileWriter("E:/aaa666/a.txt",true);
        String str1 = "我也这么觉得";
        writer1.write(str1);
        writer1.flush();
        writer1.close();
    }
}

 输出结果如下图所示:

2.3 Reader字符输入流

public class Test1 {
    public static void main(String[] args) throws Exception {
        Reader reader = new FileReader("E:/aaa666/a.txt");


        char[] chars = new char[2];
        int a = reader.read(chars);
        String s = new String(chars,0,a);
        System.out.println()
        
    }
}

用这种方式,我们可以一次读取多个字符 并存入一个字符数组中。由此我们可以引出,用while循环来输出文件的所有字符内容:

public class Test1 {
    public static void main(String[] args) throws Exception {
        Reader reader = new FileReader("E:/aaa666/a.txt");
        int count = 0;
        char[] cs = new char[5];
        while ((count = reader.read(cs)) != -1 ){
            String str = new String(cs,0,count);
            System.out.print(str);
        }
    }
}

2.4 字符流中完成文件的复制操作

要求:将我们的E:/aaa666/a.txt的内容复制到E:/AAA/f.txt。

    @Test
    public void Copy01() throws Exception{
        //1.创建一个字符输入流
        FileReader fr = new FileReader("E:/aaa666/a.txt");
        //2.创建一个字符输出流
        FileWriter fw = new FileWriter("E:/AAA/f.txt");
        int c = 0;//读取到字符的个数
        char[] chars = new char[10];//每次读取的内容放入该数
        while ((c = fr.read(chars)) != -1){
            fw.write(chars,0,c);
            fw.flush();//刷新
        }
        fw.close();
        fr.close();
    }

        注意:我们的文件目录都是事先存在的,如果文件目录不存在,那么解决方法也很简单,只需加一个判读条件,判断我们的fw是否为exists()或者是否为Directory(),如果不是,则fw.mkdir();即可。

        我们的字符流复制的操作,并不能将一个视频文件或者图片文件进行复制,只能对文本进行操作。因为视频和图片格式的文件都属于二进制。那么,想要实现这个功能,就需要我们的字节流来实现了。下面为大家讲述一下字节流。

2.5 字节流

2.5.1 字节输出流——OutputStream

        字节输出流可以对任意文件进行写操作,对文件进行输出操作。以字节为单位。 它是所有字节输出流的父类,例如FileOutputStream。接下来我们测试一下字节输出流。

    @Test
    public void OutputStream01() throws Exception{
        OutputStream os = new FileOutputStream("E:/aaa666/zzz.txt");
        String str = "abcdefg";
        //把字符串转换为字节数组.
        byte[] bytes = str.getBytes();
        os.write(bytes);
        os.flush();
        os.close();
    }

2.5.2 字节输入流——InputStream

        字节输入流可以对任意文件进行读操作以字节为单位,它是所有字节输入流的父类,子类有FileInputStream。读取的方法有两种:

第一种:一次一次的读取:

    @Test
    public void IntputStream01() throws Exception{
        InputStream is = new FileInputStream("E:/aaa666/a.txt");
        byte[] bytes = new byte[3];//一次读取三个字节 并把读取的内容放入字节数组中  返回读取到字节的个数
        int read = is.read(bytes);
        System.out.println(bytes+"   读取个数:"+read);
        read = is.read(bytes);
        System.out.println(bytes+"   读取个数:"+read);
        read = is.read(bytes);
        System.out.println(bytes+"   读取个数:"+read);
    }

第二种:如果文件内容非常大,使用循环来读取

    @Test
    public void for01() throws Exception{
        InputStream is = new FileInputStream("E:/aaa666/a.txt");
        byte[] bytes = new byte[5];
        int c = 0;//读取到的个数
        while ((c = is.read(bytes)) != -1){
            //把byte数组转换为字符串
            String str = new String(bytes,0,c);
            System.out.println(str);
        }
        is.close();
    }

2.5.3 字节流复制操作

要求:我们复制一张名为1.jpg的图片。在这里把图片给大家,省的大家再去找,当然你可以随便用任何一张图片。

 代码如下:原理和字符流的复制相同,这里就不再进行过多累述

    @Test
    public void Copy01() throws Exception{
        InputStream is = new FileInputStream("E:/aaa666/1.jpg");
        OutputStream os = new FileOutputStream("E:/AAA/2.jpg");
        byte[] bytes = new byte[5];
        int c = 0;
        while ((c=is.read(bytes)) != -1){
            os.write(bytes,0,c);
        }
        is.close();
        os.close();
    }

2.6 缓存流

        缓存流是在基础流[InputStream OutputStream Reader Writer]之上 添加了一个缓存池功能.
BufferInutStream  BufferOutputStream BufferReader  BufferWriter 提高IO的效率,降低IO的次数。

        我们写的内容,通过缓存流的操作,让内容暂时的放入了缓存池中,并没有直接放入文件中,所以在我们刷新缓存池之前,我们的文件并没有写入内容。我们可以直接通过close方法来实现缓存池的刷新操作。因为close是先刷新后关闭。

    @Test
    public void Buffer01() throws Exception{
        OutputStream os = new FileOutputStream("E:/aaa666/ttt.txt");
        BufferedOutputStream bos = new BufferedOutputStream(os);
        String str = "今天是阴天";
        byte[] bytes = str.getBytes();
        bos.write(bytes);
        bos.close();
    }
    @Test
    public void Buffer02() throws Exception{
        InputStream is = new FileInputStream("E:/aaa666/a.txt");
        BufferedInputStream bos = new BufferedInputStream(is);
        byte[] bytes =new byte[10];
        int c = 0;
        while ((c=bos.read(bytes)) != -1){
            String str = new String(bytes,0,c);
            System.out.println(str);
        }
        bos.close();
    }

2.7 对象流——对Java对象进行IO操作

        为什么我们需要用到对象流呢? 我们现在操作IO流的时候 都是将字符串读写操作 可不可以将java对象在文件中进行读写呢?

        当然是可以的          例如写入一个 Student st=new Student();对象
  将java对象进行读写操作 意义在于持久化信息  例如: 游戏存档。

        这里还有一个概念,就是序列化和反序列化。通俗的讲,序列化相当于存档,就是要我们的对象类型的数据,必须实现Serializable接口,才能进行写入操作。反序列化相当于读档,就是让我们文件里的对象内容输出到idea中方便查看。(直接点开文件查看对象内容是乱码)

首先我们创建一个Student类,必须有Serializable接口:

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

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

    public String getName() {
        return name;
    }

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

    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
    }

    public int getAge() {
        return age;
    }

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

    public String getJineng() {
        return jineng;
    }

    public void setJineng(String jineng) {
        this.jineng = jineng;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", level='" + level + '\'' +
                ", age=" + age +
                ", jineng='" + jineng + '\'' +
                '}';
    }
}

序列化:

    @Test
    public void ObjectOutputStream01() throws Exception{
        OutputStream os = new FileOutputStream("E:/aaa666/a111.txt");
        ObjectOutputStream oos = new ObjectOutputStream(os);
        Student s = new Student("张三","7级",20,"乌鸦坐飞机");
        oos.writeObject(s);
        oos.close();
    }

我们直接点开文档查看时看不懂的

想要查看对象内容,就需要反序列化:

    @Test
    public void ObjectInputStream01() throws Exception{
        InputStream is = new FileInputStream("E:/aaa666/a111.txt");
        ObjectInputStream ois = new ObjectInputStream(is);
        Object o = ois.readObject();
        System.out.println(o);
        ois.close();
    }

 运行以后输出的效果如下图所示:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值