Java - I/O - 详细文件操作

159 阅读4分钟

Java 文件操作

在 Java 中,文件操作是非常常见的需求。无论是处理文本文件、二进制文件,还是递归查找和创建文件,Java 提供了强大的 I/O(输入输出)API 来支持这些操作。本文将全面介绍 Java 中关于文件操作的相关知识,包括 I/O 流 API、文件的读写操作、递归查找、文件创建等方面。

1. Java I/O 流概述

Java 中的文件操作是通过 I/O 流来实现的。I/O 流分为两大类:输入流和输出流。每一类又分为字节流和字符流。

1.1 字节流与字符流

  • 字节流:处理原始的二进制数据,适用于所有类型的文件(文本文件、图片文件、音频文件等)。字节流类以 InputStreamOutputStream 为基类。
  • 字符流:专门处理字符数据,适用于文本文件。字符流类以 ReaderWriter 为基类。

1.2 常见的 I/O 类

  • 字节流类
    • FileInputStreamFileOutputStream:用于字节流读取和写入文件。
    • BufferedInputStreamBufferedOutputStream:为字节流提供缓冲功能,提高读写性能。
  • 字符流类
    • FileReaderFileWriter:用于字符流读取和写入文件。
    • BufferedReaderBufferedWriter:为字符流提供缓冲功能,提高性能。
  • 数据流类
    • DataInputStreamDataOutputStream:用于读写原始数据类型(如 intdouble 等),确保跨平台兼容性。
  • 对象流类
    • ObjectInputStreamObjectOutputStream:用于读写 Java 对象(需要对象实现 Serializable 接口)。

2. 文件的基本读写操作

2.1 读取文件

使用字节流和字符流可以进行文件的读取操作。

2.1.1 使用 FileInputStream 读取文件(字节流)
import java.io.FileInputStream;
import java.io.IOException;

public class FileReaderExample {
    public static void main(String[] args) {
        String filePath = "example.txt";
        try (FileInputStream fileInputStream = new FileInputStream(filePath)) {
            int byteData;
            while ((byteData = fileInputStream.read()) != -1) {
                // 读取文件内容并输出
                System.out.print((char) byteData);  
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
2.1.2 使用 FileReader 读取文件(字符流)
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;

public class FileReaderCharExample {
    public static void main(String[] args) {
        String filePath = "example.txt";
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                // 输出每一行
                System.out.println(line);  
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2 写入文件

2.2.1 使用 FileOutputStream 写入文件(字节流)
import java.io.FileOutputStream;
import java.io.IOException;

public class FileWriterExample {
    public static void main(String[] args) {
        String content = "Hello, Java File I/O!";
        try (FileOutputStream fileOutputStream = new FileOutputStream("output.txt")) {
            // 写入字节数据
            fileOutputStream.write(content.getBytes());  
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
2.2.2 使用 FileWriter 写入文件(字符流)
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;

public class FileWriterCharExample {
    public static void main(String[] args) {
        String content = "Hello, Java File I/O!";
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
            // 写入字符串
            writer.write(content);  
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 递归操作文件:查找、创建文件和目录

3.1 递归查找文件

Java 8 引入了 java.nio.file 包,其中 Files.walk 方法可以用来递归遍历目录并查找文件。

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public class FileRecursiveSearch {
    public static void main(String[] args) {
        Path startDir = Paths.get("path/to/your/directory");
        try {
            Files.walkFileTree(startDir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    // 输出找到的文件
                    System.out.println("Found file: " + file);  
                    return FileVisitResult.CONTINUE;
                }
                
                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    System.err.println("Failed to access: " + file);
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.2 递归创建目录和文件

使用 Files.createDirectories 来递归创建目录,如果目录已经存在,则不会抛出异常。

import java.io.IOException;
import java.nio.file.*;

public class DirectoryRecursiveCreate {
    public static void main(String[] args) {
        Path path = Paths.get("path/to/your/directory/subdir");
        try {
            // 递归创建目录
            Files.createDirectories(path);  
            System.out.println("Directory created successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. 文件复制与移动

Java 提供了 Files.copyFiles.move 方法,用于文件的复制和移动操作。

4.1 复制文件

import java.io.IOException;
import java.nio.file.*;

public class FileCopyExample {
    public static void main(String[] args) {
        Path source = Paths.get("source.txt");
        Path destination = Paths.get("destination.txt");
        try {
            // 复制文件,覆盖目标文件
            Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING);  
            System.out.println("File copied successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4.2 移动文件

import java.io.IOException;
import java.nio.file.*;

public class FileMoveExample {
    public static void main(String[] args) {
        Path source = Paths.get("source.txt");
        Path destination = Paths.get("destination.txt");
        try {
            // 移动文件,覆盖目标文件
            Files.move(source, destination, StandardCopyOption.REPLACE_EXISTING);  
            System.out.println("File moved successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5. 文件删除

可以使用 Files.deleteFiles.deleteIfExists 来删除文件。

import java.io.IOException;
import java.nio.file.*;

public class FileDeleteExample {
    public static void main(String[] args) {
        Path path = Paths.get("fileToDelete.txt");
        try {
            // 删除文件
            Files.delete(path);  
            System.out.println("File deleted successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

6. 常见的文件操作问题及解决方案

  • 文件不存在:使用 FileNotFoundException 异常来捕获文件未找到的情况。
  • 权限问题:确保文件和目录具有足够的读写权限。
  • 字符编码:在读取和写入文本文件时,确保指定正确的字符编码(如 UTF-8)。
  • I/O 性能:对于大文件,建议使用缓冲流(如 BufferedReaderBufferedWriter)来提高性能。

7. 总结

Java 提供了丰富的 I/O API 来处理各种文件操作,包括字节流和字符流的读写、文件递归查找、文件的创建、删除、复制和移动等操作。通过灵活运用这些工具,可以方便地处理文件相关的任务。

希望本文能帮助你更好地理解 Java 中的文件操作。如果你有任何问题或需要进一步了解某个操作,可以随时提问!