文件操作 IO

文件(File)

狭义的文件: 指的是硬盘上的文件和目录
广义的文件: 泛指计算机中很多软硬件资源(操作系统中把很多硬件和软件资源抽象成了文件, 按照文件的方式同意管理)

本章内容只讨论狭义的文件

路径

  1. 绝对路径: 以c: , d: 盘符开头的路径
  2. 相对路径: 以当前所在的目录为基准(工作目录), 以. 或 … 开头(有时 . 可以省略), 找到指定的路径

那么我们的IDEA的工作路径在哪呢?
IDEA 的工作路径默认就是在当前的项目所在目录
在这里插入图片描述

Java 对于文件的操作

  1. 针对文件系统操作(文件的创建, 删除, 重命名)
  2. 针对文件内容的操作(文件的读和写)

Java 标准库中提供了File这个类

文件操作 IO_第1张图片
parent 表示当前文件所在目录
child 表示自身的文件名

        File file = new File("d:/text.txt");

构建一个File 对象

import java.io.File;
import java.io.IOException;

public class IODemo1 {
    public static void main(String[] args) throws IOException {
        File file = new File("./test1.txt");
        // 获取文件名
        System.out.println(file.getName());

        // 获取父级路径
        System.out.println(file.getParent());

        // 获取完整路径
        System.out.println(file.getPath());

        // 获取绝对路径
        System.out.println(file.getAbsoluteFile());

        // 获取绝对路径的简化路径
        System.out.println(file.getCanonicalPath());
    }
}

判断文件

import java.io.File;

public class IODemo2 {
   public static void main(String[] args) {
       File file = new File("d:/f1/f2/test1.txt");
       // 这个文件是否存在
       System.out.println(file.exists());

       // 这是不是一个文件
       System.out.println(file.isFile());

       // 这是一个目录吗
       System.out.println(file.isDirectory());
   }
}

创建文件

import java.io.File;
import java.io.IOException;

public class ThreadDemo3 {
    public static void main(String[] args) throws IOException {
        File file = new File("./test.txt");
        //创建这个文件
        file.createNewFile();
    }
}

文件操作 IO_第2张图片
删除文件

import java.io.File;

public class IODemo4 {
    public static void main(String[] args) {
        File file = new File("./test.txt");
        // 删除文件
        file.delete();
    }
}

deleteOnExit


import java.io.File;
import java.io.IOException;

public class IODemo5 {
    public static void main(String[] args) throws IOException {
        File file = new File("test.txt");
        System.out.println(file.exists());
        System.out.println(file.createNewFile());
        System.out.println(file.exists());
        //程序运行结束后删除
        file.deleteOnExit();
        System.out.println(file.exists());
    }
}

目录的创建

import java.io.File;

public class IODemo6 {
    public static void main(String[] args) {
        File dir = new File("d:/f1/f2/f3/f3");
        dir.mkdir();   // 只能创建一级目录
        dir.mkdirs();  // 创建多级目录
    }
}

文件的重命名

import java.io.File;

public class IODemo7 {
    public static void main(String[] args) {
        File file = new File("./aaa/bbb/test.txt");
        File file1 = new File("./aaa/bbb/test2.txt");
        file.renameTo(file1);
    }
}

Java 标准库的流对象

从类型上分成两个大类

  1. 字节流: 操作二进制数据的
  2. 字符流: 操作文本数据

文件操作 IO_第3张图片
read 无参数版本:一次只读一个字节
read 有一个参数版本: 把读到的内容填充到参数的这个字节数组中, (此处的参数是一个输出型参数), 返回值是实际读取的字节数
read 有三个参数的版本: 和一个参数的差不多. 只不过是往数组的一部分区间里尽可能填充

思考:

read 读取的是一个字节, 按理说应该返回一个 byte , 但是实际上是返回int, 这是为什么呢?
这里除了表示byte里的0~255 (-128 ~ 127) 这样的情况外, 还需要表示一个特殊情况, -1,这个标记表示读取文件结束了(读到末尾了).

UTF-8 每个汉字三个字节

字节流读取:

import java.io.*;

public class IODemo8 {
    // 使用字节流读取文件
    public static void main(String[] args) throws IOException {
        // 创建InputStream 对象的时候, 使用绝对路径或者相对路径都行, 也可以使用File对象
        InputStream inputStream = new FileInputStream("d:/test.txt");

//        //进行读操作
//        while (true) {
//            int b = inputStream.read();
//            if(b == -1) {
//                // 读取完毕
//                break;
//            }
//            //System.out.println(""+ (byte)b);
//            System.out.printf("%x",(byte)b);
//        }

            while (true) {
                byte[] buffer = new byte[1024];
                int len = inputStream.read(buffer);
                System.out.println("len: "+ len);
                if (len == -1) {
                    break;
                }
                // 此时读取的字符就被放到了byte[] 中了.
                for (int i = 0; i < len; i++) {
                    System.out.printf("%x\n", (byte)buffer[i]);
                }
            }

            inputStream.close();
    }
}

buffer 存在的意义,是为了提高 IO 操作的效率,
单次 IO 操作, 是要访问硬盘的, 所以就会比较耗费时间,
缩短了 IO 操作的次数, 所以效率也就提高了

字节流写文件
文件操作 IO_第4张图片
也是类似的三个方法

public class IODemo9 {
    // 进行写文件
    public static void main(String[] args) throws IOException {
        OutputStream outputStream = new FileOutputStream("d:/test.txt");
        outputStream.write(97);
        outputStream.write(98);
        outputStream.write(99);
        outputStream.write(100);
        outputStream.close();
    }
}

文件操作 IO_第5张图片
更推荐的写法
这个写法虽然没有显示的写 close , 但是在 try 语句执行完的时候, 会自动执行到 close

public class IODemo {
    public static void main(String[] args) throws IOException {
        try (OutputStream outputStream = new FileOutputStream("d:/test.txt")) {
            outputStream.write(97);
            outputStream.write(97);
            outputStream.write(97);
            outputStream.write(97);
            outputStream.write(97);
            outputStream.write(97);
        }
    }
}

字符流读文件

package io;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class IODemo10 {
    // 字符流的操作
    public static void main(String[] args) {
        try (Reader reader = new FileReader("d:/test.txt")) {
            while (true) {
                int ch = reader.read();
                if (ch == -1) {
                    break;
                }
                System.out.println("" + (char)ch);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

字符流写文件

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class IODemo11 {
    // 字符流写文件
    public static void main(String[] args) {
        try (Writer writer = new FileWriter("d:/test.txt")) {
            writer.write("hello world");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

下面我们实现一个删除文件的小程序

import java.io.File;
import java.util.Scanner;

public class IODemo12 {
    private static Scanner scanner = new Scanner(System.in);
    public static void main(String[] args) {
        // 让用户输入一个指定搜索的目录
        System.out.println("请输入一个要搜索的路径: ");
        String basePath = scanner.next();

        // 针对用户输入进行简单判定,
        File root = new File(basePath);
        if (!root.isDirectory()) {
            // 路径不存在, 或者是一个普通文件, 此时无法进行搜索
            System.out.println("输入的路径有误");
            return;
        }

        System.out.println("请输入要删除的文件名: ");
        // 此处使用 next, 不用 next.Line
        String nameToDelete = scanner.next();

        // 针对指定路径进行扫描, 递归操作
        // 先从根目录出发(root)
        // 先看看这个目录是否有我们要删除的文件, 如果有就删除, 否则下一个
        // 如果是包含了一些目录, 那就进行递归

        scanDir(root,nameToDelete);
    }

    private static void scanDir(File root, String nameToDelete) {
        // 1. 先列出当前路径下包含和目录
        File[] files = root.listFiles();
        if (files == null) {
            // 当前目录没东西, 进行下一步递归
            return;
        }
        // 遍历当前列出的结果
        for (File f: files) {
            if (f.isDirectory()) {
                // 如果是目录就进一步递归
                scanDir(f,nameToDelete);
            } else {
                // 如果是文件就判断
                if (f.getName().contains(nameToDelete)) {
                    System.out.println("确认要删除 " + f.getName() + "吗?");
                String choice = scanner.next();
                   if (choice.equals("Y") || choice.equals("y")) {
                        f.delete();
                       System.out.println("删除成功");
                   } else {
                       System.out.println("删除取消");
                   }
                }
            }
        }
    }
}

文件的复制
就是把一个文件按照字节一次读取, 把结果写入另一个文件中

import java.io.*;
import java.util.Scanner;

// 文件的拷贝
public class IODemo13 {
    public static void main(String[] args) throws RuntimeException {
        // 输入两个路径 一个源 一个目标路径 (从哪里拷贝到哪)
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要拷贝哪个文件: ");
        String srePath = scanner.next();
        System.out.println("请输入要拷贝到哪个地方: ");
        String destPath = scanner.next();

        File srcFile = new File(srePath);
        if (!srcFile.isFile()) {
            System.out.println("您输入的源路径有误!");
            return;
        }
        File destFile = new File(destPath);
        if (destFile.isFile()) {
            // 如果已经存在不能拷贝
            System.out.println("您输入的目标路径有误: ");
            return;
        }

        // 进行拷贝操作
        try (InputStream inputStream = new FileInputStream(srcFile);
             OutputStream outputStream = new FileOutputStream(destFile)) {

            // 进行读文件操作
            while (true) {
                int b = inputStream.read();
                if (b == -1) {
                    break;
                }
                outputStream.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

你可能感兴趣的:(JavaEE,java,开发语言)