File类知识梳理(包含输入输出流的使用)

前言 

学习的思维导图

 

目录

1. File类是什么?

2. 关于文件系统的操作

3. 关于文件内容的操作

3.1 文本文件

3.2 二进制文件

4. 案例实现练习

5.拓展:try with resources 操作


1. File类是什么?

      ● 概念

         它的实例化对象是对硬盘上文件或目录的抽象表示.文件存储在硬盘上,我们如果直接去操作会很不方便,所以我们可以在内存中创建对应对象,然后通过操作该对象去间接影响硬盘上的文件.在java语言中,我们可以通过如下方式抽象化表示某个路径下的某个文件.它的父类和实现接口如下:

      ● 示例代码

        System.out.println("请输入要扫描的指定目录:>");
        Scanner s = new Scanner(System.in); //可以是当前项目下的相对路径,也可以是绝对路径
        String dir = s.nextLine();
        File file = new File(dir);

2. 关于文件系统的操作

       这里不介绍所有操作,只介绍常用操作,大家先看这个图:

① 这是我本地用于测试的目录:

②  具体练习代码:

public class FileTest2 {
    public static void main(String[] args) throws IOException {
        File f = new File("E:\\比特就业课\\Java\\io测试目录");
        System.out.println(f.getParent());
        System.out.println(f.getName());
        System.out.println(f.getPath());
        System.out.println(f.getAbsolutePath());
        System.out.println(f.getCanonicalPath());
        System.out.println(f.exists());
        System.out.println(f.isDirectory());
        System.out.println(f.isFile());
        //原地创建一个由该抽象路径名命名的新的空文件
        //如果命名文件已经存在返回false,不存在创建新文件并返回true
        System.out.println(f.createNewFile());
        File f2 = new File("E:\\比特就业课\\Java\\io测试目录\\test222.txt");
        System.out.println(f2.delete());
        File testF = new File("E:\\测试单个目录创建");
        System.out.println(testF.mkdir());
        File testF2 = new File("E:\\测试多个目录创建\\direct1\\direct2");
        System.out.println(testF2.mkdirs());
        String[] content = f.list();
        assert content != null;
        for (String item:content) {
            System.out.print(item + " ");
        }
        System.out.println();
        File[] content2 = f.listFiles();
        assert content2 != null;
        for (File item:content2) {
            System.out.print(item.getName() + " ");
        }
        System.out.println();
        System.out.println(f.renameTo(testF));
    }
}

③ 执行结果:

 注:当前测试目录并不在项目路径底下.


3. 关于文件内容的操作

3.1 文本文件

         文本文件是基于字符编码的文件,常见的编码有ASCII编码,Unicode编码等等.这里先给大家引入一个"流"的概念,可以将它想象成水管,流中流动的不是水,而是字节序列.从流中读取一个字节序列的对象称为输入流,向流中写入一个字节序列的对象称为输出流.而流又可以分为两类,一个是字节流(处理基本单位是字节),另一个是字符流(处理基本单位是字符).

         我们通常使用字符流来处理文本数据,Java中对应的字符流基本抽象类为Reader和Writer,它们的直接子类是InputStreamReader,OutputStreamWriter.但是一般我们实例化的是它们的间接子类:

FileReader和FileWriter.下面我们来练习一下文本文件的读取和写入吧~测试文本文件内容如下:

         ● 示例代码

        File f = new File("E:\\某个目录\\Java\\io测试目录\\test222.txt");
        //读数据
        try (Reader reader = new FileReader(f)){
            StringBuilder stringBuilder = new StringBuilder();
            while (true) {
                int ret = reader.read();
                if (ret == -1) break; //文件读取到末尾
                stringBuilder.append((char) ret);
            }
            System.out.println(stringBuilder.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        //写数据
        try (Writer writer = new FileWriter(f)){
            StringBuilder stringBuilder = new StringBuilder("早安,全世界");
            writer.write(stringBuilder.toString()); //也可以一个字符一个字符的写
        } catch (IOException e) {
            e.printStackTrace();
        }

         ● 执行结果

   

 

注:不同的编码格式,一个字符所占的字节大小不一样.

3.2 二进制文件

         二进制文件是基于值编码的文件,没有字符集限制,什么都能存.

         我们通常使用字节流来处理二进制数据,Java中对应的字符流基本抽象类为InputStream和OutputStream,它们的直接子类是FileInputStream,FileOutputStream.因为二进制文件我们是难以看懂的,为了方便我们看懂,下面我们使用字节流来处理一下文本文件内容分析一下,测试文本文件内容如下:

         ● 示例代码

        File f = new File("E:\\比特就业课\\Java\\io测试目录\\test222.txt");
        //读数据(二进制)
        try (InputStream inputStream = new FileInputStream(f)){
            while (true) {
                int ret = inputStream.read();
                if (ret == -1) break;
                System.out.print((char)ret + " "); //得到的字符集十进制值转换成字符
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        //写数据(二进制)
        try (OutputStream outputStream = new FileOutputStream(f)){
            byte[] data = new byte[1024];
            byte b = 65;
            for (int i = 0; i < 26; i++) {
                data[i] = b;
                b++;
            }
            outputStream.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        }

         ● 执行结果

         大家可能就有疑问了,我的文本内容明明是HELLO WORLD为什么读出来是这些数字,认真看这些数字,大家会发现这些是对应字符的ASCII码值,因为字节流处理的基本单位是字节.如果文本内容是中文,那么就会根据对应的字符集编码,得到一个汉字多少个字节,假设一个汉字是2个字节,那么输出的就是对应字符编码的十进制数值.

        我们将得到的结果转成字符型,那么得到的就是我们想要的效果了(写也是类似):

        此时文本文件中显示的对应ASCII的字符.

注:文件的打开,使用完毕后,一定要进行关闭,不然会导致文件资源一直被占用.


4. 案例实现练习

      扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录).

● 具体思路:

   ① 得到给定的目录及所需查找的内容.

   ② 递归遍历给定目录的子目录.

   ③ 得到子目录下的所有内容,如果是文件就获取它的内容,目录就继续递归遍历.其它类型的内容我们暂时不做考虑.

● 实现代码:

public class FileTest {
    public static void main(String[] args) {
        //扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
        System.out.println("请输入要扫描的指定目录:>");
        Scanner s = new Scanner(System.in);
        String dir = s.nextLine();
        File file = new File(dir);
        if(!file.isDirectory()) {
            System.out.println("目录不存在");
            return;
        }

        //要查找的内容
        System.out.println("请输入要查找的内容>");
        String search = s.nextLine();
        //递归遍历子目录
        recurFile(file,search);
    }

    private static void recurFile(File file, String search) {
        File[] files = file.listFiles();
        if(files == null) {
            return;
        }
        for (File item : files) {
//            System.out.println(file.getAbsoluteFile());
            if(item.isFile()) {
                //获得文件的内容
                String ret = getContent(item);
                if(ret.contains(search)) {
                    System.out.println(item.getAbsoluteFile() + " " + ret);
                }
            } else if(item.isDirectory()) {
                recurFile(item,search);
            } else {
                continue;
            }
        }
    }

    private static String getContent(File file) {
        StringBuilder str = new StringBuilder();
        try (Reader inputStream = new FileReader(file)){
            int ret;
            while (true) {
                ret = inputStream.read();
                if(ret == -1) break;
                str.append((char) ret);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return str.toString();
    }
}

注:这里采用递归扫描方式并不高效,目的只是单纯熟悉文件操作.


5.拓展:try with resources 操作

     try with resources操作是带有资源释放的try操作,不过一定是要实现了Closeable接口的类.因为Reader,Writer,InputStream,OutputStream类都实现了Closeable接口,所以才可以通过try with resources操作进行资源的自动释放.


分享完毕~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值