文件操作——IO

1.文件

1.1 基础介绍

  • 文件是在硬盘上存储数据的操作,操作系统把硬盘的一些细节给封装起来了,我们只需要了解文件相关的接口即可.
  • 硬盘是用来存储数据的,和内存相比,硬盘的存储空间更大,访问速度更慢,成本更低,持久化存储.
  • 站在操作系统的角度看待,目录也是文件:

    ①普通文件(通常见到的文件)

    ②目录文件(通常见到的文件夹)

  • 操作系统通过"文件系统"这样的模块来管理硬盘.

比如说:

这里的C,D,E盘并不是真正的硬盘,实际上电脑中只有一个硬盘,操作系统通过文件系统把这个硬盘抽象成了多个硬盘.

  • 不同的文件系统,管理文件的方式是类似的,通过 目录-文件 构成了"N叉树"树形结构

1.2 文件路径

①路径: 

D->tmp->bag.jpq 通过这个路线可以找到电脑上唯一一个文件,这个东西就成为"路径".

使用/或\来分割不同的目录.

②绝对路径:

以盘符开头的路径,叫做"绝对路径",相当于从"此电脑"出发,找文件的过程.(d:/tmp/bag.jpq)

③相对路径:

以.或..开头的路径,叫做"相对路径",需要一个"基准目录"/"工作目录".

比如:

如果以D:为基准目录,相对路径为./tmp/bag.jpq(这个.表示当前所在目录)

如果以D:/tmp为基准目录,相对路径为./bag.jpq(这个.表示当前所在目录)

如果以D:/tmp/11为基准目录,相对路径为../bag.jpq(这个..表示当前所在目录的上一层目录)

如果以D:/tmp/11/aa为基准目录,相对路径为../../bag.jpq

注:同样是一个cat.jpq文件,站在不同的基准目录中,查找的路径是不同的.

1.3 文件类型

文件系统上存储的文件,具体开始又分为两个大类:

①文本文件(存储的是字符)

②二进制文件(存储的是二进制的数据)

 2.Java中操作文件

Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述.(io即input和output)

我们站在cpu的视角来看待输入输出:

通过File对象来描述一个具体的文件,可以对应到一个真实存在的文件,也可以对应到一个不存在的文件.

2.1 构造方法

2.2 方法

修饰符及返回 值类型方法签名说明
StringgetParent()返回 File 对象的父目录文件路径
StringgetName()返回 FIle 对象的纯文件名称
StringgetPath()返回 File 对象的文件路径
StringgetAbsolutePath()返回 File 对象的绝对路径
StringgetCanonicalPath()返回 File 对象的修饰过的绝对路径
booleanexists()判断 File 对象描述的文件是否真实存在
booleanisDirectory()判断 File 对象代表的文件是否是一个目录
booleanisFile()判断 File 对象代表的文件是否是一个普通文件
booleancreateNewFile()根据 File 对象,自动创建一个空文件。成功创建后返 回 true
booleandelete()根据 File 对象,删除该文件。成功删除后返回 true
voiddeleteOnExit()根据 File 对象,标注文件将被删除,删除动作会到 JVM 运行结束时才会进行
String[]list()返回 File 对象代表的目录下的所有文件名
File[]listFiles()返回 File 对象代表的目录下的所有文件,以 File 对象 表示
booleanmkdir()创建 File 对象代表的目录
booleanmkdirs()创建 File 对象代表的目录,如果必要,会创建中间目 录
booleanrenameTo(File dest)进行文件改名,也可以视为我们平时的剪切、粘贴操作
booleancanRead()判断用户是否对文件有可读权限
booleancanWrite()判断用户是否对文件有可写权限

 

3.文件内容的读写 —— 数据流

 

3.1 Reader用法 

//Reader用法
public class Demo6 {
    public static void main(String[] args) throws IOException {
        //FileReader构造方法,可以填写一个文件路径(绝对路径/相对路径都行,也可以填写一个构造好的File对象)
        //Reader reader = new FileReader("e:/test.txt");//抽象类
        //抛出异常,或者return,这里的close就执行不到了
        /*try {

        }finally {
            reader.close();//这个操作非常重要,释放必要的资源
            //一旦一直打开文件,而不去关闭不用的文件,文件描述符表就会被占满,后续就无法继续打开新的文件
        }*/


        //使用try with resources是更好的解决方案
        try(Reader reader = new FileReader("e:/test.txt")) {
            //try代码块执行完毕,会自动调用到close方法,类似于synchronized
            while (true){
                char buf[] = new char[1024];//通过read,就会把本来一个空的数组,填充上内容
                int n = reader.read(buf);
                if (n == -1){
                    break;//读到文件末尾了
                }
                for (int i = 0; i< n; i++){
                    System.out.print(buf[i] + " ");
                }
            }
        }

    }
}

 3.2 InputStream用法

//InputStream用法
public class Demo7 {
    public static void main(String[] args) throws IOException {
        try(InputStream inputStream = new FileInputStream("d:/test.txt")) {
            //文本文件也可以使用字节流打开,只不过此时读到的每个字节,就不是完整字符了
            while (true){
                byte[] buf = new byte[1024];
                int n = inputStream.read(buf);
                if (n == -1){
                    break;
                }
                for (int i = 0; i < n;i++){
                    System.out.print(buf[i]+ " ");
                }
                String s = new String(buf,0,n);//字节数组转成字符串
                System.out.println(s);
            }
        }
    }
}

注:

InputStream 只是一个抽象类,要使用还需要具体的实现类。现在只关心从文件中读取,所以使用 FileInputStream 

FileInputStream构造方法:

public class Demo8 {
    public static void main(String[] args) throws IOException {
        try(InputStream inputStream = new FileInputStream("e:/test.txt")) {
            Scanner scanner = new Scanner(inputStream);
            //此时就是从test.txt中读取文件了
            String s = scanner.next();
            System.out.println(s);
        }
    }
}

3.3 Writer用法

//使用Writer
public class Demo9 {
    public static void main(String[] args) throws IOException {
        try(Writer writer = new FileWriter("e:/test.txt",true)) {
            //write可以一次直接写一个字符串,比较方便
            writer.write("xixixi");

        }
    }
}

补充:

OutputStream使用方法一样,只不过write方法,不能支持字符串参数,只能按照字节或者字节数组来写入.

OutputStream 同样只是一个抽象类,要使用还需要具体的实现类。我们现在还是只关心写入文件中, 所以使用 FileOutputStream

PrintWriter搭配OutputStream来简化代码,提供一系列方法,写的结果是写入文件中了...

 

4.练习

4.1 题目一 

public class Demo10 {

    private static Scanner scanner = new Scanner(System.in);
    public static void main(String[] args) {

        //1.让用户输入一个目录,后续的查找都是针对这个目录的
        System.out.println("请输入要搜素的目录: ");
        File rooPath = new File(scanner.next());
        //2.让用户输入要搜索/删除的关键词
        System.out.println("请输入要删除的关键词: ");
        String word = scanner.next();
        //3.判断一下当前输入的目录是否有效
        if (!rooPath.isDirectory()){
            System.out.println("您此时输入的路径不是合法目录!");
            return;
        }
        //4.遍历目录,从根目录出发,按照深度优先的方式,进行遍历
        scanDir(rooPath,word);

    }

    public static void scanDir(File currentDir,String word){
        //1.先列出当前目录中都包含哪些内容
        File[] files = currentDir.listFiles();
        if (files == null || files.length == 0){
            //空目录或非法目录
            return;
        }
        //2.遍历列出的文件,分两个情况分别讨论
        for (File f : files){
            //加个日志,方便看程序执行的过程
            System.out.println(f.getAbsoluteFile());

            if (f.isFile()){
                //3.如果当前文件是普通文件,看看是否包含了word,来决定是否要删除
                dealFile(f,word);
            }else {
                //4.如果当前文件就目录文件,就递归执行scanDir
                scanDir(f,word);
            }
        }
    }

    private static void dealFile(File f, String word){
        //1.先判定当前文件名是否包含word
        if (!f.getName().contains(word)){
            //此时这个文件不包含关键字,直接跳过
            return;
        }

        //2,包含word,询问用户是否删除该文件
        System.out.println("请输入该文件是:" +f.getAbsoluteFile() + "是否要删除?y/n");
        String choice = scanner.next();
        if (choice.equals("y")||choice.equals("Y")){
            f.delete();
        }
        //如果是其它,忽略
    }
}

4.2 题目二 

public class Demo11 {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        //1.输入路径,合法性判定
        System.out.println("请输入要复制的文件路径: ");
        String src = scanner.next();
        File srcFile = new File(src);
        if (!srcFile.isFile()){
            System.out.println("您要复制的源文件路径是非法的");
            return;
        }
        System.out.println("请输入要复制到的目标路径:");
        String dest = scanner.next();
        File destFile = new File(dest);
        //不要求目标文件本身存在,要求其所在的目录存在
        if (!destFile.getParentFile().isDirectory()){
            System.out.println("您要复制到的目标路径是非法的");
            return;
        }

        //2.进行复制操作的过程,按照字节流打开:(文本二进制都可以按照字节流方式操作)
        try (InputStream inputStream = new FileInputStream(srcFile);
        OutputStream outputStream = new FileOutputStream(destFile)){
            while (true){
                byte[] buffer = new byte[1024];
                int n = inputStream.read(buffer);
                System.out.println("n = " +n);
                if (n ==-1){
                    System.out.println("读取到eof,循环结束");
                    break;
                }
                //把读到的内容写入
                outputStream.write(buffer,0,n);

            }
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值