Java 文件操作

文章目录

  • Java 文件操作
    • 构造方法
    • 文件属性操作
    • 文件内容操作
      • InputStream
      • Reader
      • OutputStream
      • Writer
    • 更多案例
      • 文件查找
      • 普通文件的复制

Java 文件操作

Java 中通过 java.io.File 类来对文件进行描述。

构造方法

构造方法 说明
File(String pathname) 通过路径名字符串来创建 File 实例
File(String parent, String child) 从父路径名字符串和子路径名字符串创建 File 实例
File(File parent, String child) 从父抽象路径名和子路径名字符串创建 File 实例

注意:创建 File 实例不等于创建文件

文件属性操作

方法 说明
String getParent() 返回父路径名字符串
String getName() 返回该抽象路径名表示的文件或目录的名称
String getPath() 将此抽象路径名转换为路径名字符串
String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
String getCanonicalPath() 返回此抽象路径名的规范路径名字符串
boolean exists() 测试此抽象路径名表示的文件或目录是否存在
boolean isDirectory() 测试此抽象路径名表示的文件是否为目录
boolean isFile() 测试此抽象路径名表示的文件是否为普通文件
boolean createNewFile() 当且仅当具有此名称的文件还不存在时,原子地创建一个由该抽象路径名命名的新的空文件。
boolean delete() 删除由该抽象路径名表示的文件或目录
void deleteOnExit() 请求在虚拟机终止时删除由该抽象路径名表示的文件或目录
String[] list() 返回该抽象路径名下的文件名
File[] listFiles() 返回一个抽象路径名数组,表示该抽象路径名所表示的目录中的文件
boolean mkdir() 创建以此抽象路径名命名的目录
boolean mkdirs() 创建以此抽象路径名命名的目录,如果必要,会创建中间目录
boolean renameTo(File dest) 重命名由该抽象路径名表示的文件
boolean canRead() 测试应用程序是否可以读取由该抽象路径名表示的文件
boolean canWrite() 测试应用程序是否可以修改由该抽象路径名表示的文件

示例:

public static void main(String[] args) throws IOException {
    File file = new File("d:/test.txt");
    System.out.println(file.getParent()); // d:\
    System.out.println(file.getName()); // test.txt
    System.out.println(file.getPath()); // d:\test.txt
    System.out.println(file.getAbsolutePath()); // d:\test.txt
    System.out.println(file.getCanonicalPath()); // D:\test.txt
}
public static void main(String[] args) throws IOException {
    File file = new File("helloworld.txt");
    System.out.println(file.exists()); // false
    System.out.println(file.isDirectory()); // false
    System.out.println(file.isFile()); // false
    System.out.println("=============================");
    // 创建文件
    file.createNewFile();
    System.out.println(file.exists()); // true
    System.out.println(file.isDirectory()); // false
    System.out.println(file.isFile()); // true
}
public static void main(String[] args) {
    File file = new File("helloworld.txt");
    // 删除文件
    file.delete();
    System.out.println(file.exists()); // false
}
public static void main(String[] args) throws IOException, InterruptedException {
    File file = new File("helloworld.txt");
    // 把文件创建回来
    file.createNewFile();
    // 在程序退出前删除
    file.deleteOnExit();
    Thread.sleep(5000);
    System.out.println(file.exists()); // true
}
public static void main(String[] args) {
    // 创建目录
    File file = new File("test");
    System.out.println(file.exists()); // false
    System.out.println(file.isDirectory()); // false
    System.out.println("========================");
    file.mkdir();
    System.out.println(file.exists()); // true
    System.out.println(file.isDirectory()); // true
}
public static void main(String[] args) {
    // 创建多级目录
    File file = new File("test/a/b/c");
    System.out.println(file.exists()); // false
    System.out.println(file.isDirectory()); // false
    System.out.println("========================");
    file.mkdirs();
    System.out.println(file.exists()); // true
    System.out.println(file.isDirectory()); // true
}
public static void main(String[] args) throws IOException {
    // 文件重命名
    File file1 = new File("test1.txt");
    File file2 = new File("test2.txt");
    file1.createNewFile(); // 创建 test1.txt
    file1.renameTo(file2); // 重命名成 test2.txt
}

文件内容操作

相关的类:

  • 字节流:InputStream OutputStream,用于操作二进制文件
  • 字符流:Reader Writer,用于操作文本文件

InputStream

方法 说明
int read() 从输入流中读取下一个字节的数据。值字节以 int 形式返回,其范围为 0 到 255。如果由于到达流的末尾而没有可用的字节,则返回值 -1。此方法会阻塞,直到输入数据可用、检测到流的末尾或引发异常为止。
int read(byte b[]) 从输入流中读取一定数量的字节,并将其存储到数组 b 中,并且尽可能把 b 填满。实际读取的字节数以整数形式返回。此方法会阻塞,直到输入数据可用、检测到文件结尾或引发异常为止。
int read(byte b[], int off, int len) 也是把读到的字节往 b 里塞,从 off 的位置开始塞,最多塞 len 个字节

InputStream 是一个抽象类,通过 new 它的子类 FileInputStream 来实例化

// 文件内容:hello
public static void main(String[] args) throws IOException {
    // 打开文件
    InputStream inputStream = new FileInputStream("test2.txt");
    // 读取文件
    while (true) {
        int b = inputStream.read();
        if (b == -1) {
            break;
        }
        System.out.println(b);
    }
    // 关闭文件
    inputStream.close();
}
/*输出:
104
101
108
108
111
*/

这正是 hello 的 ASCII 码

要想把字节流还原成原来的文本,需要手动处理:

public static void main(String[] args) throws IOException {
    // 打开文件
    InputStream inputStream = new FileInputStream("test2.txt");
    // 读取文件
    byte[] b = new byte[1024];
    int len = inputStream.read(b);
    // 还原成文本
    String s = new String(b, 0, len, StandardCharsets.UTF_8);
    System.out.println(s);
    // 关闭文件
    inputStream.close();
}

Reader

方法 说明
int read(java.nio.CharBuffer target) 尝试将字符读取到指定的字符缓冲区中
int read() 读取单个字符。此方法将阻塞,直到字符可用、发生I/O错误或到达流的末尾
int read(char cbuf[]) 将字符读取到数组中。此方法将一直阻塞,直到某个输入可用、出现I/O错误或到达流的末尾
int read(char cbuf[], int off, int len) 将字符读入数组的一部分。此方法将一直阻塞,直到某个输入可用、出现I/O错误或到达流的末尾

使用 FileReader 实例化

例:Reader 直接读取到文本

public static void main(String[] args) throws IOException {
    Reader reader = new FileReader("test2.txt");
    char[] buffer = new char[1024];
    int len = reader.read(buffer);
    for (int i = 0; i < len; ++i) {
        System.out.println(buffer[i]);
    }
    reader.close();
}

其实读文件最方便的写法,是使用 Scanner

这个我们在标准输入的时候用过,只要把 System.in 换成其他 InputStream

public static void main(String[] args) throws IOException {
    InputStream inputStream = new FileInputStream("test2.txt");
    Scanner scanner = new Scanner(inputStream);
    String s = scanner.next();
    System.out.println(s);
    inputStream.close();
}

技巧:使用 try with resources 关闭文件

try (InputStream inputStream = new FileInputStream("test2.txt")){
    // ......
} catch (IOException e) {
    e.printStackTrace();
}

OutputStream

方法 说明
void write(int b) 将指定的字节写入此输出流
void write(byte b[]) 将指定字节数组中的 b.length 个字节写入此输出流
void write(byte b[], int off, int len) 从偏移量为 off 的指定字节数组中写入 len 个字节到此输出流
public static void main(String[] args) throws IOException {
    try (OutputStream outputStream = new FileOutputStream("test2.txt")) {
        outputStream.write('a');
        outputStream.write('b');
        outputStream.write('c');
    }
}

如果要输出一个字符串,那么需要转为字节数组:

public static void main(String[] args) throws IOException {
    try (OutputStream outputStream = new FileOutputStream("test2.txt")) {
        String s = "你好";
        outputStream.write(s.getBytes());
    }
}

注意:打开文件会清空文件内容,写的时候并不会

Writer

方法 说明
void write(int c) 写入单个字符
void write(char cbuf[]) 写入一个字符数组
void write(char cbuf[], int off, int len) 写入字符数组的一部分
void write(String str) 写入字符串
void write(String str, int off, int len) 写入字符串的一部分
public static void main(String[] args) throws IOException {
    try (Writer writer = new FileWriter("test2.txt")) {
        writer.write("hello world");
    }
}

使用 PrintWriter 包装一下

public static void main(String[] args) throws IOException {
    try (OutputStream outputStream = new FileOutputStream("test2.txt")) {
        PrintWriter printWriter = new PrintWriter(outputStream);
        // 此处 printWriter 的用法就和 System.out 类似了
        printWriter.println("aaa");
        printWriter.flush();
    }
}

注意PrintWriter 自带缓冲区,如果你写的内容太短,可能需要 flush 一下

更多案例

文件查找

递归查找目录下的所有文件,将文件名包含指定字符串的文件删除

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

public class demo {
    public static void main(String[] args) throws IOException {
        System.out.println("请输入要扫描的路径:");
        Scanner scanner = new Scanner(System.in);
        String rootPath = scanner.next();
        File root = new File(rootPath);
        if (!root.exists()) {
            System.out.println("输入的路径不存在");
            return;
        }
        System.out.println("请输入要删除的文件名(或部分):");
        String toDelete = scanner.next();

        // 递归删除文件
        scanDir(root, toDelete);
    }
    public static void scanDir(File rootDir, String toDelete) throws IOException {
        File[] files = rootDir.listFiles();
        if (files == null) {
            return;
        }
        for (File f : files) {
            if (f.isDirectory()) {
                scanDir(f, toDelete);
            } else {
                tryDelete(f, toDelete);
            }
        }
    }

    public static void tryDelete(File f, String toDelete) throws IOException {
        if (f.getName().contains(toDelete)) {
            System.out.println("是否删除文件(y/n):" + f.getCanonicalPath());
            Scanner scanner = new Scanner(System.in);
            String choice = scanner.next();
            if (choice.equals("y")) {
                f.delete();
            }
        }
    }
}

普通文件的复制

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

public class demo {
    public static void main(String[] args) throws IOException {
        System.out.println("请输入要复制的文件路径:");
        Scanner scanner = new Scanner(System.in);
        String srcPath = scanner.next();
        File srcFile = new File(srcPath);
        if (!srcFile.exists()) {
            System.out.println("文件不存在");
            return;
        }
        if (!srcFile.isFile()) {
            System.out.println("不是普通文件");
            return;
        }
        System.out.println("请输入目标路径:");
        String destPath = scanner.next();
        File destFile = new File(destPath);
        if (destFile.exists()) {
            System.out.println("目标已经存在");
            return;
        }

        // 开始复制
        try (InputStream inputStream = new FileInputStream(srcFile);
             OutputStream outputStream = new FileOutputStream(destFile)) {
            byte[] buf = new byte[1024];
            while (true) {
                int len = inputStream.read(buf);
                if (len == -1) {
                    // 拷贝完成
                    break;
                }
				outputStream.write(buf, 0, len);
            }
        }
        System.out.println("复制完成");
    }
}

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