Java I/O 详解:基础、文件操作与 NIO 实践
Java I/O (输入输出) 是指用于读取和写入数据的 API,包括从文件、网络和其他数据源进行读取和写入操作。Java 提供了丰富的类和接口来实现各种 I/O 操作,主要包括标准 I/O、文件 I/O 和新 I/O (NIO)。以下是 Java I/O 的详细介绍:
一、基本 I/O
1. 字节流 (Byte Streams)
字节流用于处理原始二进制数据,通常用于处理图片、音频、视频等二进制文件。
- 输入流 (InputStream):
- FileInputStream: 从文件中读取字节流。
- ByteArrayInputStream: 从字节数组中读取数据。
- BufferedInputStream: 为其他输入流添加缓冲功能。
- 输出流 (OutputStream):
- FileOutputStream: 将字节流写入文件。
- ByteArrayOutputStream: 将数据写入字节数组。
- BufferedOutputStream: 为其他输出流添加缓冲功能。
2. 字符流 (Character Streams)
字符流用于处理文本数据,字符流以 16 位 Unicode 字符为单位处理数据。
- 输入流 (Reader):
- FileReader: 从文件中读取字符流。
- StringReader: 从字符串中读取字符数据。
- BufferedReader: 为其他字符输入流添加缓冲功能,并提供按行读取的功能。
- 输出流 (Writer):
- FileWriter: 将字符流写入文件。
- StringWriter: 将字符数据写入字符串。
- BufferedWriter: 为其他字符输出流添加缓冲功能。
二、文件 I/O
Java 提供了 File 类用于表示文件和目录,提供了多种方法来操作文件和目录。
- File 类常用方法:
- createNewFile(): 创建一个新的文件。
- mkdir(), mkdirs(): 创建一个或多个目录。
- delete(): 删除文件或目录。
- list(), listFiles(): 列出目录中的文件和子目录。
三、新 I/O (NIO)
NIO (New I/O) 引入了一些高效的 I/O 操作方式,包括缓冲区 (Buffers)、通道 (Channels) 和选择器 (Selectors)。
1. 缓冲区 (Buffers)
缓冲区是一个容器对象,用于特定基本数据类型的元素的线性、有限序列。NIO 缓冲区比传统 I/O 更加高效。
- 常用缓冲区类型:
- ByteBuffer: 存储字节数据。
- CharBuffer: 存储字符数据。
- IntBuffer, LongBuffer, DoubleBuffer 等其他基本类型的缓冲区。
2. 通道 (Channels)
通道是用于 I/O 操作的对象,它能够读写数据,但不直接操作数据,而是通过缓冲区来进行操作。
- 常用通道类型:
- FileChannel: 用于文件的读写操作。
- SocketChannel: 用于 TCP 网络连接的读写操作。
- DatagramChannel: 用于 UDP 网络连接的读写操作。
3. 选择器 (Selectors)
选择器允许一个线程管理多个通道的 I/O 操作。通过使用选择器,可以在一个单独的线程中管理多个通道,从而提高了效率。
- 常用方法:
- select(): 阻塞直到至少有一个通道准备好了 I/O 操作。
- selectNow(): 非阻塞地进行选择操作。
- selectedKeys(): 返回准备好的通道的键集合。
四、文件操作示例
1. 使用 File 类
import java.io.File; import java.io.IOException; public class FileExample { public static void main(String[] args) { File file = new File("example.txt"); // 创建文件 try { if (file.createNewFile()) { System.out.println("File created: " + file.getName()); } else { System.out.println("File already exists."); } } catch (IOException e) { e.printStackTrace(); } // 检查文件是否存在 if (file.exists()) { System.out.println("File exists."); // 获取文件信息 System.out.println("File name: " + file.getName()); System.out.println("Absolute path: " + file.getAbsolutePath()); System.out.println("Writeable: " + file.canWrite()); System.out.println("Readable: " + file.canRead()); System.out.println("File size in bytes: " + file.length()); } } }
2. 使用字节流进行文件复制
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class FileCopyExample { public static void main(String[] args) { try (FileInputStream fis = new FileInputStream("source.txt"); FileOutputStream fos = new FileOutputStream("destination.txt")) { int byteContent; while ((byteContent = fis.read()) != -1) { fos.write(byteContent); } } catch (IOException e) { e.printStackTrace(); } } }
3. 使用字符流读写文件
import java.io.BufferedReader; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class FileReadWriteExample { public static void main(String[] args) { // 写入文件 try (FileWriter writer = new FileWriter("example.txt")) { writer.write("Hello, World!\n"); writer.write("Java I/O example."); } catch (IOException e) { e.printStackTrace(); } // 读取文件 try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } }
4. 使用 NIO 进行文件复制
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class NIOFileCopyExample { public static void main(String[] args) { Path sourcePath = Paths.get("source.txt"); Path destinationPath = Paths.get("destination.txt"); try { Files.copy(sourcePath, destinationPath); } catch (IOException e) { e.printStackTrace(); } } }
这些示例展示了如何使用 Java I/O 和 NIO 进行文件操作。了解和掌握这些知识点有助于开发高效、可靠的 Java 应用程序。