Java I/O 流
Java I/O(输入/输出)流是Java中处理数据输入和输出的核心机制。通过I/O流,程序可以读取文件、写入文件、从网络接收数据或向网络发送数据。
字节流与字符流
Java I/O流主要分为两大类:字节流和字符流。字节流以字节为单位处理数据,适用于处理二进制数据;字符流以字符为单位处理数据,适用于处理文本数据。
字节流
字节流的基类是InputStream和OutputStream,它们是所有字节流类的父类。
java
import java.io.*;
// 字节流示例
public class ByteStreamExample {
public static void main(String[] args) {
System.out.println("=== 字节流示例 ===");
// 1. 文件字节流 - FileInputStream和FileOutputStream
fileByteStreamExample();
// 2. 缓冲字节流 - BufferedInputStream和BufferedOutputStream
bufferedByteStreamExample();
// 3. 数据字节流 - DataInputStream和DataOutputStream
dataByteStreamExample();
// 4. 对象字节流 - ObjectInputStream和ObjectOutputStream
objectByteStreamExample();
}
// 文件字节流示例
public static void fileByteStreamExample() {
System.out.println("\n--- 文件字节流示例 ---");
String fileName = "byte_example.txt";
String content = "Hello, Java Byte Stream!\n这是一个字节流示例。";
// 写入文件
try (FileOutputStream fos = new FileOutputStream(fileName)) {
byte[] bytes = content.getBytes("UTF-8");
fos.write(bytes);
System.out.println("数据已写入文件: " + fileName);
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
}
// 读取文件
try (FileInputStream fis = new FileInputStream(fileName)) {
byte[] buffer = new byte[1024];
int bytesRead;
System.out.print("从文件读取的数据: ");
while ((bytesRead = fis.read(buffer)) != -1) {
System.out.print(new String(buffer, 0, bytesRead, "UTF-8"));
}
System.out.println();
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
}
// 缓冲字节流示例
public static void bufferedByteStreamExample() {
System.out.println("\n--- 缓冲字节流示例 ---");
String fileName = "buffered_example.txt";
// 使用缓冲输出流写入大量数据
try (FileOutputStream fos = new FileOutputStream(fileName);
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
// 写入大量数据
for (int i = 0; i < 1000; i++) {
String line = "这是第" + (i + 1) + "行数据\n";
bos.write(line.getBytes("UTF-8"));
}
// 缓冲流会自动刷新缓冲区
System.out.println("大量数据已写入文件: " + fileName);
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
}
// 使用缓冲输入流读取数据
try (FileInputStream fis = new FileInputStream(fileName);
BufferedInputStream bis = new BufferedInputStream(fis)) {
long startTime = System.currentTimeMillis();
byte[] buffer = new byte[1024];
int totalBytes = 0;
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
totalBytes += bytesRead;
}
long endTime = System.currentTimeMillis();
System.out.println("读取字节数: " + totalBytes);
System.out.println("读取耗时: " + (endTime - startTime) + " ms");
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
}
// 数据字节流示例
public static void dataByteStreamExample() {
System.out.println("\n--- 数据字节流示例 ---");
String fileName = "data_example.dat";
// 使用DataOutputStream写入各种数据类型
try (FileOutputStream fos = new FileOutputStream(fileName);
DataOutputStream dos = new DataOutputStream(fos)) {
dos.writeUTF("Java数据流示例");
dos.writeInt(12345);
dos.writeDouble(3.14159);
dos.writeBoolean(true);
dos.writeFloat(2.5f);
System.out.println("不同类型的数据已写入文件");
} catch (IOException e) {
System.err.println("写入数据时发生错误: " + e.getMessage());
}
// 使用DataInputStream读取数据
try (FileInputStream fis = new FileInputStream(fileName);
DataInputStream dis = new DataInputStream(fis)) {
String text = dis.readUTF();
int number = dis.readInt();
double pi = dis.readDouble();
boolean flag = dis.readBoolean();
float value = dis.readFloat();
System.out.println("读取的数据:");
System.out.println(" 字符串: " + text);
System.out.println(" 整数: " + number);
System.out.println(" 双精度浮点数: " + pi);
System.out.println(" 布尔值: " + flag);
System.out.println(" 单精度浮点数: " + value);
} catch (IOException e) {
System.err.println("读取数据时发生错误: " + e.getMessage());
}
}
// 对象字节流示例
public static void objectByteStreamExample() {
System.out.println("\n--- 对象字节流示例 ---");
String fileName = "object_example.ser";
// 创建要序列化的对象
Person person = new Person("张三", 25, "zhangsan@example.com");
Book book = new Book("Java编程思想", "Bruce Eckel", 89.0);
// 序列化对象
try (FileOutputStream fos = new FileOutputStream(fileName);
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(person);
oos.writeObject(book);
System.out.println("对象已序列化到文件: " + fileName);
System.out.println("序列化的对象:");
System.out.println(" " + person);
System.out.println(" " + book);
} catch (IOException e) {
System.err.println("序列化对象时发生错误: " + e.getMessage());
}
// 反序列化对象
try (FileInputStream fis = new FileInputStream(fileName);
ObjectInputStream ois = new ObjectInputStream(fis)) {
Person deserializedPerson = (Person) ois.readObject();
Book deserializedBook = (Book) ois.readObject();
System.out.println("反序列化的对象:");
System.out.println(" " + deserializedPerson);
System.out.println(" " + deserializedBook);
// 验证对象是否完全恢复
System.out.println("对象恢复验证:");
System.out.println(" 姓名匹配: " + person.getName().equals(deserializedPerson.getName()));
System.out.println(" 年龄匹配: " + (person.getAge() == deserializedPerson.getAge()));
System.out.println(" 书籍名称匹配: " + book.getTitle().equals(deserializedBook.getTitle()));
} catch (IOException | ClassNotFoundException e) {
System.err.println("反序列化对象时发生错误: " + e.getMessage());
}
}
}
// 用于序列化的Person类
class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private String email;
public Person(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
// getter方法
public String getName() { return name; }
public int getAge() { return age; }
public String getEmail() { return email; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", email='" + email + "'}";
}
}
// 用于序列化的Book类
class Book implements Serializable {
private static final long serialVersionUID = 1L;
private String title;
private String author;
private double price;
public Book(String title, String author, double price) {
this.title = title;
this.author = author;
this.price = price;
}
// getter方法
public String getTitle() { return title; }
public String getAuthor() { return author; }
public double getPrice() { return price; }
@Override
public String toString() {
return "Book{title='" + title + "', author='" + author + "', price=" + price + "}";
}
}字符流
字符流的基类是Reader和Writer,它们专门用于处理字符数据,自动处理字符编码转换。
java
import java.io.*;
import java.nio.charset.StandardCharsets;
// 字符流示例
public class CharacterStreamExample {
public static void main(String[] args) {
System.out.println("=== 字符流示例 ===");
// 1. 文件字符流 - FileReader和FileWriter
fileCharacterStreamExample();
// 2. 缓冲字符流 - BufferedReader和BufferedWriter
bufferedCharacterStreamExample();
// 3. PrintWriter示例
printWriterExample();
// 4. InputStreamReader和OutputStreamWriter示例
streamConverterExample();
}
// 文件字符流示例
public static void fileCharacterStreamExample() {
System.out.println("\n--- 文件字符流示例 ---");
String fileName = "char_example.txt";
String content = "Hello, Java Character Stream!\n这是一个字符流示例。\n支持中文字符的正确处理。";
// 使用FileWriter写入文件
try (FileWriter writer = new FileWriter(fileName, StandardCharsets.UTF_8)) {
writer.write(content);
System.out.println("文本已写入文件: " + fileName);
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
}
// 使用FileReader读取文件
try (FileReader reader = new FileReader(fileName, StandardCharsets.UTF_8)) {
char[] buffer = new char[1024];
int charsRead;
System.out.print("从文件读取的文本: ");
while ((charsRead = reader.read(buffer)) != -1) {
System.out.print(new String(buffer, 0, charsRead));
}
System.out.println();
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
}
// 缓冲字符流示例
public static void bufferedCharacterStreamExample() {
System.out.println("\n--- 缓冲字符流示例 ---");
String fileName = "buffered_char_example.txt";
// 使用BufferedWriter写入文件
try (FileWriter fileWriter = new FileWriter(fileName, StandardCharsets.UTF_8);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) {
// 写入多行文本
for (int i = 1; i <= 100; i++) {
bufferedWriter.write("这是第" + i + "行文本");
bufferedWriter.newLine(); // 写入换行符
}
// 使用write方法写入字符数组
char[] chars = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'};
bufferedWriter.write(chars);
bufferedWriter.newLine();
System.out.println("多行文本已写入文件: " + fileName);
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
}
// 使用BufferedReader读取文件
try (FileReader fileReader = new FileReader(fileName, StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(fileReader)) {
String line;
int lineCount = 0;
int charCount = 0;
// 逐行读取
while ((line = bufferedReader.readLine()) != null) {
lineCount++;
charCount += line.length();
// 仅打印前5行和最后一行
if (lineCount <= 5 || lineCount == 101) {
System.out.println("第" + lineCount + "行: " + line);
} else if (lineCount == 6) {
System.out.println("...");
}
}
System.out.println("总行数: " + lineCount);
System.out.println("总字符数: " + charCount);
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
}
// PrintWriter示例
public static void printWriterExample() {
System.out.println("\n--- PrintWriter示例 ---");
String fileName = "print_example.txt";
// 使用PrintWriter格式化输出
try (PrintWriter printWriter = new PrintWriter(
new BufferedWriter(new FileWriter(fileName, StandardCharsets.UTF_8)))) {
// 打印各种数据类型
printWriter.println("=== 学生成绩单 ===");
printWriter.printf("%-10s %-10s %-10s%n", "姓名", "科目", "成绩");
printWriter.println("------------------------");
// 打印学生成绩
printWriter.printf("%-10s %-10s %-10.1f%n", "张三", "数学", 95.5);
printWriter.printf("%-10s %-10s %-10.1f%n", "张三", "英语", 87.0);
printWriter.printf("%-10s %-10s %-10.1f%n", "李四", "数学", 92.0);
printWriter.printf("%-10s %-10s %-10.1f%n", "李四", "英语", 88.5);
// 计算并打印平均分
printWriter.println();
printWriter.println("平均分:");
printWriter.printf("%-10s %-10s %-10.2f%n", "张三", "平均", (95.5 + 87.0) / 2);
printWriter.printf("%-10s %-10s %-10.2f%n", "李四", "平均", (92.0 + 88.5) / 2);
System.out.println("格式化数据已写入文件: " + fileName);
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
}
// 读取并显示文件内容
try (BufferedReader reader = new BufferedReader(
new FileReader(fileName, StandardCharsets.UTF_8))) {
String line;
System.out.println("文件内容:");
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
}
// InputStreamReader和OutputStreamWriter示例
public static void streamConverterExample() {
System.out.println("\n--- 字符流转换器示例 ---");
String fileName = "converter_example.txt";
// 使用OutputStreamWriter指定编码写入
try (FileOutputStream fos = new FileOutputStream(fileName);
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {
String content = "这是使用OutputStreamWriter写入的内容\n支持指定字符编码\n可以正确处理中文等Unicode字符";
osw.write(content);
System.out.println("使用指定编码写入文件: " + fileName);
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
}
// 使用InputStreamReader指定编码读取
try (FileInputStream fis = new FileInputStream(fileName);
InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8)) {
char[] buffer = new char[1024];
int charsRead;
System.out.print("使用指定编码读取的内容: ");
while ((charsRead = isr.read(buffer)) != -1) {
System.out.print(new String(buffer, 0, charsRead));
}
System.out.println();
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
// 演示不同编码的效果
demonstrateEncoding();
}
// 演示不同编码的效果
public static void demonstrateEncoding() {
System.out.println("\n--- 编码演示 ---");
String text = "Hello 世界 🌍";
System.out.println("原始文本: " + text);
// 不同编码的字节长度
try {
byte[] utf8Bytes = text.getBytes(StandardCharsets.UTF_8);
byte[] utf16Bytes = text.getBytes(StandardCharsets.UTF_16);
byte[] isoBytes = text.getBytes(StandardCharsets.ISO_8859_1);
System.out.println("UTF-8编码字节数: " + utf8Bytes.length);
System.out.println("UTF-16编码字节数: " + utf16Bytes.length);
System.out.println("ISO-8859-1编码字节数: " + isoBytes.length);
// 使用错误编码读取会出现乱码
String wrongDecode = new String(utf8Bytes, StandardCharsets.ISO_8859_1);
System.out.println("使用错误编码读取: " + wrongDecode);
} catch (Exception e) {
System.err.println("编码演示时发生错误: " + e.getMessage());
}
}
}文件操作(File 类)
File类是Java中表示文件和目录路径名的抽象表示形式,它提供了许多用于文件和目录操作的方法。
java
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Date;
// File类操作示例
public class FileExample {
public static void main(String[] args) {
System.out.println("=== File类操作示例 ===");
// 1. File类基本操作
basicFileOperations();
// 2. 目录操作
directoryOperations();
// 3. 文件过滤和查找
fileFiltering();
// 4. 文件属性操作
fileAttributes();
// 5. 临时文件操作
temporaryFiles();
// 6. 文件路径操作
pathOperations();
}
// File类基本操作
public static void basicFileOperations() {
System.out.println("\n--- File类基本操作 ---");
// 创建File对象的多种方式
File file1 = new File("example.txt");
File file2 = new File("directory", "example.txt");
File file3 = new File("directory/example.txt");
File file4 = new File(new File("directory"), "example.txt");
System.out.println("File对象创建方式:");
System.out.println(" 相对路径: " + file1.getPath());
System.out.println(" 父目录+文件名: " + file2.getPath());
System.out.println(" 完整路径: " + file3.getPath());
System.out.println(" File对象+文件名: " + file4.getPath());
// 文件创建和删除
try {
File testFile = new File("test_file.txt");
// 创建新文件
if (testFile.createNewFile()) {
System.out.println("文件创建成功: " + testFile.getAbsolutePath());
} else {
System.out.println("文件已存在: " + testFile.getAbsolutePath());
}
// 写入一些内容
try (FileWriter writer = new FileWriter(testFile)) {
writer.write("这是测试文件的内容\n");
writer.write("创建时间: " + new Date());
}
// 文件信息
System.out.println("文件信息:");
System.out.println(" 绝对路径: " + testFile.getAbsolutePath());
System.out.println(" 规范路径: " + testFile.getCanonicalPath());
System.out.println(" 文件名: " + testFile.getName());
System.out.println(" 父目录: " + testFile.getParent());
System.out.println(" 文件大小: " + testFile.length() + " 字节");
System.out.println(" 是否存在: " + testFile.exists());
System.out.println(" 是否为文件: " + testFile.isFile());
System.out.println(" 是否为目录: " + testFile.isDirectory());
System.out.println(" 最后修改时间: " + new Date(testFile.lastModified()));
// 删除文件
if (testFile.delete()) {
System.out.println("文件删除成功: " + testFile.getPath());
} else {
System.out.println("文件删除失败: " + testFile.getPath());
}
} catch (IOException e) {
System.err.println("文件操作时发生错误: " + e.getMessage());
}
}
// 目录操作
public static void directoryOperations() {
System.out.println("\n--- 目录操作 ---");
// 创建目录
File dir = new File("test_directory");
if (dir.mkdir()) {
System.out.println("目录创建成功: " + dir.getAbsolutePath());
} else {
System.out.println("目录已存在或创建失败: " + dir.getAbsolutePath());
}
// 创建多级目录
File nestedDir = new File("parent/child/grandchild");
if (nestedDir.mkdirs()) {
System.out.println("多级目录创建成功: " + nestedDir.getAbsolutePath());
} else {
System.out.println("多级目录已存在或创建失败: " + nestedDir.getAbsolutePath());
}
// 在目录中创建文件
try {
File file1 = new File(dir, "file1.txt");
File file2 = new File(dir, "file2.txt");
file1.createNewFile();
file2.createNewFile();
System.out.println("在目录中创建文件:");
System.out.println(" " + file1.getName());
System.out.println(" " + file2.getName());
// 列出目录内容
String[] files = dir.list();
if (files != null) {
System.out.println("目录内容:");
for (String fileName : files) {
System.out.println(" " + fileName);
}
}
// 使用File对象列出内容
File[] fileObjects = dir.listFiles();
if (fileObjects != null) {
System.out.println("详细目录信息:");
for (File file : fileObjects) {
System.out.printf(" %-20s %-10s %-20s%n",
file.getName(),
file.isDirectory() ? "<DIR>" : file.length() + " bytes",
new Date(file.lastModified()));
}
}
} catch (IOException e) {
System.err.println("目录操作时发生错误: " + e.getMessage());
}
// 删除目录(必须为空)
File emptyDir = new File("empty_directory");
if (emptyDir.mkdir()) {
if (emptyDir.delete()) {
System.out.println("空目录删除成功: " + emptyDir.getPath());
} else {
System.out.println("空目录删除失败: " + emptyDir.getPath());
}
}
}
// 文件过滤和查找
public static void fileFiltering() {
System.out.println("\n--- 文件过滤和查找 ---");
// 创建测试目录和文件
File testDir = new File("filter_test");
testDir.mkdir();
try {
// 创建不同类型的测试文件
new File(testDir, "document.txt").createNewFile();
new File(testDir, "image.jpg").createNewFile();
new File(testDir, "data.csv").createNewFile();
new File(testDir, "archive.zip").createNewFile();
new File(testDir, "script.js").createNewFile();
new File(testDir, "style.css").createNewFile();
// 使用FilenameFilter过滤
String[] txtFiles = testDir.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".txt");
}
});
System.out.println("文本文件 (.txt):");
if (txtFiles != null) {
for (String file : txtFiles) {
System.out.println(" " + file);
}
}
// 使用FileFilter过滤
File[] imageFiles = testDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isFile() && pathname.getName().endsWith(".jpg");
}
});
System.out.println("图片文件 (.jpg):");
if (imageFiles != null) {
for (File file : imageFiles) {
System.out.println(" " + file.getName());
}
}
// Lambda表达式过滤(Java 8+)
File[] largeFiles = testDir.listFiles(file -> file.length() > 0);
System.out.println("非空文件:");
if (largeFiles != null) {
for (File file : largeFiles) {
System.out.println(" " + file.getName() + " (" + file.length() + " bytes)");
}
}
} catch (IOException e) {
System.err.println("文件过滤操作时发生错误: " + e.getMessage());
}
}
// 文件属性操作
public static void fileAttributes() {
System.out.println("\n--- 文件属性操作 ---");
try {
File file = new File("attribute_test.txt");
if (file.createNewFile()) {
System.out.println("创建测试文件: " + file.getName());
}
// 设置文件属性
System.out.println("文件属性:");
System.out.println(" 可读: " + file.canRead());
System.out.println(" 可写: " + file.canWrite());
System.out.println(" 可执行: " + file.canExecute());
// 修改文件时间戳
long newTime = System.currentTimeMillis() - 24 * 60 * 60 * 1000; // 24小时前
if (file.setLastModified(newTime)) {
System.out.println("修改最后修改时间成功");
}
// 使用NIO.2获取更详细的文件属性
Path path = file.toPath();
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("详细文件属性 (NIO.2):");
System.out.println(" 创建时间: " + attrs.creationTime());
System.out.println(" 最后访问时间: " + attrs.lastAccessTime());
System.out.println(" 最后修改时间: " + attrs.lastModifiedTime());
System.out.println(" 是否为目录: " + attrs.isDirectory());
System.out.println(" 是否为常规文件: " + attrs.isRegularFile());
System.out.println(" 是否为符号链接: " + attrs.isSymbolicLink());
System.out.println(" 文件大小: " + attrs.size() + " 字节");
} catch (IOException e) {
System.err.println("文件属性操作时发生错误: " + e.getMessage());
}
}
// 临时文件操作
public static void temporaryFiles() {
System.out.println("\n--- 临时文件操作 ---");
try {
// 创建临时文件
File tempFile = File.createTempFile("temp_", ".txt");
System.out.println("临时文件创建成功: " + tempFile.getAbsolutePath());
// 写入临时文件
try (FileWriter writer = new FileWriter(tempFile)) {
writer.write("这是一个临时文件\n");
writer.write("程序退出时应该被删除");
}
// 读取临时文件
try (BufferedReader reader = new BufferedReader(new FileReader(tempFile))) {
String line;
System.out.println("临时文件内容:");
while ((line = reader.readLine()) != null) {
System.out.println(" " + line);
}
}
// 设置退出时删除
tempFile.deleteOnExit();
System.out.println("已设置程序退出时删除临时文件");
// 创建临时目录
Path tempDir = Files.createTempDirectory("temp_dir_");
System.out.println("临时目录创建成功: " + tempDir.toAbsolutePath());
// 在临时目录中创建文件
Path tempFileInDir = tempDir.resolve("test.txt");
Files.write(tempFileInDir, "临时目录中的文件".getBytes(StandardCharsets.UTF_8));
System.out.println("临时目录中的文件: " + tempFileInDir.toAbsolutePath());
// 设置临时目录退出时删除
tempDir.toFile().deleteOnExit();
tempFileInDir.toFile().deleteOnExit();
} catch (IOException e) {
System.err.println("临时文件操作时发生错误: " + e.getMessage());
}
}
// 文件路径操作
public static void pathOperations() {
System.out.println("\n--- 文件路径操作 ---");
// 使用不同分隔符
String path1 = "dir1" + File.separator + "dir2" + File.separator + "file.txt";
String path2 = "dir1/dir2/file.txt"; // Unix风格
String path3 = "dir1\\dir2\\file.txt"; // Windows风格
System.out.println("不同分隔符的路径:");
System.out.println(" 系统分隔符: " + path1);
System.out.println(" Unix风格: " + path2);
System.out.println(" Windows风格: " + path3);
// 路径信息提取
File file = new File("/home/user/documents/report.pdf");
System.out.println("路径信息:");
System.out.println(" 完整路径: " + file.getPath());
System.out.println(" 绝对路径: " + file.getAbsolutePath());
System.out.println(" 文件名: " + file.getName());
System.out.println(" 父目录: " + file.getParent());
System.out.println(" 不带扩展名的文件名: " + getFileNameWithoutExtension(file));
System.out.println(" 文件扩展名: " + getFileExtension(file));
// 相对路径和绝对路径转换
File relativeFile = new File("data/config.xml");
System.out.println("相对路径转换:");
System.out.println(" 相对路径: " + relativeFile.getPath());
System.out.println(" 绝对路径: " + relativeFile.getAbsolutePath());
System.out.println(" 规范路径: " + relativeFile.getCanonicalPath());
}
// 获取不带扩展名的文件名
public static String getFileNameWithoutExtension(File file) {
String fileName = file.getName();
int dotIndex = fileName.lastIndexOf('.');
return dotIndex > 0 ? fileName.substring(0, dotIndex) : fileName;
}
// 获取文件扩展名
public static String getFileExtension(File file) {
String fileName = file.getName();
int dotIndex = fileName.lastIndexOf('.');
return dotIndex > 0 ? fileName.substring(dotIndex + 1) : "";
}
}
// 文件工具类
class FileUtils {
// 复制文件
public static void copyFile(File source, File destination) throws IOException {
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(destination);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
}
}
// 递归删除目录
public static void deleteDirectory(File directory) throws IOException {
if (directory.isDirectory()) {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
deleteDirectory(file);
}
}
}
if (!directory.delete()) {
throw new IOException("无法删除文件或目录: " + directory.getPath());
}
}
// 计算目录大小
public static long getDirectorySize(File directory) {
long size = 0;
if (directory.isDirectory()) {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile()) {
size += file.length();
} else {
size += getDirectorySize(file);
}
}
}
}
return size;
}
// 查找文件
public static File[] findFiles(File directory, String extension) {
return directory.listFiles((dir, name) -> name.toLowerCase().endsWith(extension.toLowerCase()));
}
}
// File工具类使用示例
public class FileUtilsExample {
public static void main(String[] args) {
System.out.println("=== File工具类使用示例 ===");
try {
// 创建测试目录和文件
File testDir = new File("fileutils_test");
testDir.mkdirs();
File sourceFile = new File(testDir, "source.txt");
try (FileWriter writer = new FileWriter(sourceFile)) {
writer.write("这是源文件的内容\n用于测试文件复制功能\n包含多行文本");
}
// 测试文件复制
File destFile = new File(testDir, "destination.txt");
FileUtils.copyFile(sourceFile, destFile);
System.out.println("文件复制成功");
System.out.println("源文件大小: " + sourceFile.length() + " 字节");
System.out.println("目标文件大小: " + destFile.length() + " 字节");
// 创建子目录和文件
File subDir = new File(testDir, "subdir");
subDir.mkdir();
new File(subDir, "subfile1.txt").createNewFile();
new File(subDir, "subfile2.txt").createNewFile();
// 计算目录大小
long dirSize = FileUtils.getDirectorySize(testDir);
System.out.println("目录总大小: " + dirSize + " 字节");
// 查找特定类型文件
File[] txtFiles = FileUtils.findFiles(testDir, ".txt");
System.out.println("找到的.txt文件:");
for (File file : txtFiles) {
System.out.println(" " + file.getPath() + " (" + file.length() + " 字节)");
}
// 清理测试文件
FileUtils.deleteDirectory(testDir);
System.out.println("测试目录已清理");
} catch (IOException e) {
System.err.println("文件工具类测试时发生错误: " + e.getMessage());
}
}
}缓冲流与转换流
缓冲流和转换流是Java I/O流体系中的重要组成部分,它们提供了额外的功能来提高I/O操作的效率和灵活性。
缓冲流
缓冲流通过在内存中维护缓冲区来减少实际的I/O操作次数,从而提高性能。
java
import java.io.*;
import java.nio.charset.StandardCharsets;
// 缓冲流示例
public class BufferedStreamExample {
public static void main(String[] args) {
System.out.println("=== 缓冲流示例 ===");
// 1. 缓冲字节流性能对比
byteStreamPerformanceComparison();
// 2. 缓冲字符流性能对比
characterStreamPerformanceComparison();
// 3. 缓冲流的标记和重置功能
markAndResetExample();
// 4. 自定义缓冲区大小
customBufferSizeExample();
}
// 缓冲字节流性能对比
public static void byteStreamPerformanceComparison() {
System.out.println("\n--- 缓冲字节流性能对比 ---");
String fileName = "byte_performance_test.txt";
int dataSize = 1000000; // 1MB数据
// 创建测试数据
try {
createTestData(fileName, dataSize);
} catch (IOException e) {
System.err.println("创建测试数据时发生错误: " + e.getMessage());
return;
}
// 不使用缓冲流读取
long startTime = System.currentTimeMillis();
long bytesRead = 0;
try (FileInputStream fis = new FileInputStream(fileName)) {
int data;
while ((data = fis.read()) != -1) {
bytesRead++;
}
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
long endTime = System.currentTimeMillis();
long noBufferTime = endTime - startTime;
System.out.println("不使用缓冲流:");
System.out.println(" 读取字节数: " + bytesRead);
System.out.println(" 耗时: " + noBufferTime + " ms");
// 使用缓冲流读取
startTime = System.currentTimeMillis();
bytesRead = 0;
try (FileInputStream fis = new FileInputStream(fileName);
BufferedInputStream bis = new BufferedInputStream(fis)) {
int data;
while ((data = bis.read()) != -1) {
bytesRead++;
}
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
endTime = System.currentTimeMillis();
long bufferTime = endTime - startTime;
System.out.println("使用缓冲流:");
System.out.println(" 读取字节数: " + bytesRead);
System.out.println(" 耗时: " + bufferTime + " ms");
System.out.println(" 性能提升: " + (noBufferTime > 0 ? (double) noBufferTime / bufferTime : "N/A") + " 倍");
// 使用缓冲流批量读取
startTime = System.currentTimeMillis();
bytesRead = 0;
try (FileInputStream fis = new FileInputStream(fileName);
BufferedInputStream bis = new BufferedInputStream(fis)) {
byte[] buffer = new byte[8192];
int readBytes;
while ((readBytes = bis.read(buffer)) != -1) {
bytesRead += readBytes;
}
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
endTime = System.currentTimeMillis();
long batchBufferTime = endTime - startTime;
System.out.println("缓冲流批量读取:");
System.out.println(" 读取字节数: " + bytesRead);
System.out.println(" 耗时: " + batchBufferTime + " ms");
System.out.println(" 相比单字节读取提升: " + (bufferTime > 0 ? (double) bufferTime / batchBufferTime : "N/A") + " 倍");
}
// 缓冲字符流性能对比
public static void characterStreamPerformanceComparison() {
System.out.println("\n--- 缓冲字符流性能对比 ---");
String fileName = "char_performance_test.txt";
int lineCount = 100000; // 10万行数据
// 创建测试数据
try {
createCharacterTestData(fileName, lineCount);
} catch (IOException e) {
System.err.println("创建字符测试数据时发生错误: " + e.getMessage());
return;
}
// 不使用缓冲流逐行读取
long startTime = System.currentTimeMillis();
int linesRead = 0;
try (FileReader fr = new FileReader(fileName, StandardCharsets.UTF_8)) {
int character;
StringBuilder line = new StringBuilder();
while ((character = fr.read()) != -1) {
if (character == '\n') {
linesRead++;
line.setLength(0); // 清空行缓冲
} else {
line.append((char) character);
}
}
// 处理最后一行(如果没有换行符)
if (line.length() > 0) {
linesRead++;
}
} catch (IOException e) {
System.err.println("读取字符文件时发生错误: " + e.getMessage());
}
long endTime = System.currentTimeMillis();
long noBufferTime = endTime - startTime;
System.out.println("不使用缓冲流逐行读取:");
System.out.println(" 读取行数: " + linesRead);
System.out.println(" 耗时: " + noBufferTime + " ms");
// 使用缓冲流逐行读取
startTime = System.currentTimeMillis();
linesRead = 0;
try (FileReader fr = new FileReader(fileName, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(fr)) {
String line;
while ((line = br.readLine()) != null) {
linesRead++;
}
} catch (IOException e) {
System.err.println("读取字符文件时发生错误: " + e.getMessage());
}
endTime = System.currentTimeMillis();
long bufferTime = endTime - startTime;
System.out.println("使用缓冲流逐行读取:");
System.out.println(" 读取行数: " + linesRead);
System.out.println(" 耗时: " + bufferTime + " ms");
System.out.println(" 性能提升: " + (noBufferTime > 0 ? (double) noBufferTime / bufferTime : "N/A") + " 倍");
}
// 缓冲流的标记和重置功能
public static void markAndResetExample() {
System.out.println("\n--- 缓冲流的标记和重置功能 ---");
String content = "这是第一行文本\n这是第二行文本\n这是第三行文本\n这是第四行文本\n这是第五行文本";
try (StringReader sr = new StringReader(content);
BufferedReader br = new BufferedReader(sr)) {
// 读取第一行
String line1 = br.readLine();
System.out.println("读取第一行: " + line1);
// 设置标记,缓冲区大小为1024
br.mark(1024);
// 读取接下来的两行
String line2 = br.readLine();
String line3 = br.readLine();
System.out.println("读取第二行: " + line2);
System.out.println("读取第三行: " + line3);
// 重置到标记位置
br.reset();
System.out.println("重置后重新读取:");
// 重新读取标记后的数据
String resetLine2 = br.readLine();
String resetLine3 = br.readLine();
System.out.println("重新读取第二行: " + resetLine2);
System.out.println("重新读取第三行: " + resetLine3);
// 继续读取剩余行
String line4 = br.readLine();
String line5 = br.readLine();
System.out.println("继续读取第四行: " + line4);
System.out.println("继续读取第五行: " + line5);
} catch (IOException e) {
System.err.println("标记和重置操作时发生错误: " + e.getMessage());
}
// 演示标记失败的情况
try (StringReader sr = new StringReader(content);
BufferedReader br = new BufferedReader(sr, 16)) { // 小缓冲区
String line1 = br.readLine();
System.out.println("\n小缓冲区示例:");
System.out.println("读取第一行: " + line1);
// 设置标记
br.mark(16);
// 读取超过缓冲区大小的数据
String line2 = br.readLine();
String line3 = br.readLine();
System.out.println("读取第二行: " + line2);
System.out.println("读取第三行: " + line3);
// 尝试重置(可能会失败)
try {
br.reset();
System.out.println("重置成功");
} catch (IOException e) {
System.out.println("重置失败: " + e.getMessage());
System.out.println("原因: 读取的数据超过了标记时指定的缓冲区大小");
}
} catch (IOException e) {
System.err.println("小缓冲区示例时发生错误: " + e.getMessage());
}
}
// 自定义缓冲区大小
public static void customBufferSizeExample() {
System.out.println("\n--- 自定义缓冲区大小 ---");
String fileName = "custom_buffer_test.txt";
// 创建测试文件
try (FileWriter fw = new FileWriter(fileName, StandardCharsets.UTF_8);
BufferedWriter bw = new BufferedWriter(fw, 64)) { // 64字节缓冲区
for (int i = 1; i <= 100; i++) {
bw.write("这是第" + i + "行测试数据");
bw.newLine();
}
System.out.println("使用64字节缓冲区写入100行数据");
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
}
// 测试不同缓冲区大小的性能
testDifferentBufferSizes(fileName);
}
// 测试不同缓冲区大小的性能
private static void testDifferentBufferSizes(String fileName) {
System.out.println("\n不同缓冲区大小性能测试:");
int[] bufferSizes = {16, 64, 256, 1024, 8192};
for (int bufferSize : bufferSizes) {
long startTime = System.currentTimeMillis();
int linesRead = 0;
try (FileReader fr = new FileReader(fileName, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(fr, bufferSize)) {
String line;
while ((line = br.readLine()) != null) {
linesRead++;
}
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
continue;
}
long endTime = System.currentTimeMillis();
System.out.printf("缓冲区大小 %5d: 读取 %3d 行,耗时 %3d ms%n",
bufferSize, linesRead, endTime - startTime);
}
}
// 创建字节测试数据
private static void createTestData(String fileName, int size) throws IOException {
try (FileOutputStream fos = new FileOutputStream(fileName);
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
byte[] data = new byte[size];
for (int i = 0; i < size; i++) {
data[i] = (byte) (i % 256);
}
bos.write(data);
}
}
// 创建字符测试数据
private static void createCharacterTestData(String fileName, int lineCount) throws IOException {
try (FileWriter fw = new FileWriter(fileName, StandardCharsets.UTF_8);
BufferedWriter bw = new BufferedWriter(fw)) {
for (int i = 1; i <= lineCount; i++) {
bw.write("这是第" + i + "行测试数据,包含一些中文字符和数字123456789");
bw.newLine();
}
}
}
}转换流
转换流(InputStreamReader和OutputStreamWriter)用于在字节流和字符流之间进行转换,同时可以指定字符编码。
java
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
// 转换流示例
public class StreamConverterExample {
public static void main(String[] args) {
System.out.println("=== 转换流示例 ===");
// 1. 基本转换流使用
basicConverterUsage();
// 2. 字符编码转换
charsetConversion();
// 3. 系统默认编码处理
systemDefaultEncoding();
// 4. 转换流与缓冲流结合使用
converterWithBuffer();
// 5. 实用的编码检测和转换工具
encodingUtility();
}
// 基本转换流使用
public static void basicConverterUsage() {
System.out.println("\n--- 基本转换流使用 ---");
String text = "Hello 世界! 🌍\n这是一个转换流示例。\n支持Unicode字符。";
// 使用OutputStreamWriter将字符转换为字节
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(baos, StandardCharsets.UTF_8)) {
osw.write(text);
osw.flush(); // 确保所有数据都被写出
byte[] bytes = baos.toByteArray();
System.out.println("原始文本: " + text);
System.out.println("UTF-8编码字节数组长度: " + bytes.length);
System.out.println("前20个字节: " + Arrays.toString(Arrays.copyOf(bytes, Math.min(20, bytes.length))));
// 使用InputStreamReader将字节转换回字符
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
InputStreamReader isr = new InputStreamReader(bais, StandardCharsets.UTF_8)) {
char[] buffer = new char[1024];
int charsRead = isr.read(buffer);
String decodedText = new String(buffer, 0, charsRead);
System.out.println("解码后的文本: " + decodedText);
System.out.println("文本是否相同: " + text.equals(decodedText));
}
} catch (IOException e) {
System.err.println("转换流操作时发生错误: " + e.getMessage());
}
}
// 字符编码转换
public static void charsetConversion() {
System.out.println("\n--- 字符编码转换 ---");
String text = "Hello 世界! こんにちは! 안녕하세요!";
// 不同编码的转换
Charset[] charsets = {
StandardCharsets.UTF_8,
StandardCharsets.UTF_16,
StandardCharsets.ISO_8859_1,
Charset.forName("GBK")
};
System.out.println("原始文本: " + text);
System.out.println("文本长度: " + text.length() + " 个字符");
for (Charset charset : charsets) {
try {
// 编码为字节
byte[] encodedBytes = text.getBytes(charset);
// 解码回字符
String decodedText = new String(encodedBytes, charset);
System.out.printf("%-15s: %3d 字节, 解码正确: %s%n",
charset.name(),
encodedBytes.length,
text.equals(decodedText));
// 显示前几个字节(仅UTF-8)
if (charset == StandardCharsets.UTF_8 && encodedBytes.length > 10) {
System.out.print(" 前10个字节: ");
for (int i = 0; i < 10; i++) {
System.out.printf("%02X ", encodedBytes[i] & 0xFF);
}
System.out.println();
}
} catch (Exception e) {
System.out.printf("%-15s: 不支持或转换失败%n", charset.name());
}
}
}
// 系统默认编码处理
public static void systemDefaultEncoding() {
System.out.println("\n--- 系统默认编码处理 ---");
// 获取系统默认编码
String defaultEncoding = System.getProperty("file.encoding");
Charset defaultCharset = Charset.defaultCharset();
System.out.println("JVM参数指定的编码: " + defaultEncoding);
System.out.println("Java默认字符集: " + defaultCharset.name());
System.out.println("可用字符集数量: " + Charset.availableCharsets().size());
// 演示使用默认编码的问题
String text = "中文测试文本";
try {
// 使用默认编码
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(baos)) { // 使用默认编码
osw.write(text);
osw.flush();
byte[] bytes = baos.toByteArray();
System.out.println("\n使用默认编码 (" + osw.getEncoding() + "):");
System.out.println(" 原始文本: " + text);
System.out.println(" 字节数组: " + Arrays.toString(bytes));
System.out.println(" 字节长度: " + bytes.length);
// 使用相同编码解码
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
InputStreamReader isr = new InputStreamReader(bais)) { // 使用默认编码
char[] buffer = new char[1024];
int charsRead = isr.read(buffer);
String decoded = new String(buffer, 0, charsRead);
System.out.println(" 解码文本: " + decoded);
System.out.println(" 编码一致: " + text.equals(decoded));
}
}
} catch (IOException e) {
System.err.println("默认编码处理时发生错误: " + e.getMessage());
}
}
// 转换流与缓冲流结合使用
public static void converterWithBuffer() {
System.out.println("\n--- 转换流与缓冲流结合使用 ---");
String fileName = "converter_buffer_test.txt";
String content = "这是一个结合使用转换流和缓冲流的示例。\n" +
"通过这种方式可以提高I/O操作的效率。\n" +
"同时还能处理字符编码转换。\n" +
"适用于处理大量文本数据的场景。\n".repeat(100); // 重复100次
// 写入文件 - 转换流 + 缓冲流
long startTime = System.currentTimeMillis();
try (FileOutputStream fos = new FileOutputStream(fileName);
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
BufferedWriter bw = new BufferedWriter(osw)) {
bw.write(content);
bw.flush(); // 确保所有数据写出
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
}
long writeTime = System.currentTimeMillis() - startTime;
System.out.println("写入耗时: " + writeTime + " ms");
System.out.println("写入字符数: " + content.length());
// 读取文件 - 转换流 + 缓冲流
startTime = System.currentTimeMillis();
StringBuilder readContent = new StringBuilder();
try (FileInputStream fis = new FileInputStream(fileName);
InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
readContent.append(line).append("\n");
}
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
long readTime = System.currentTimeMillis() - startTime;
System.out.println("读取耗时: " + readTime + " ms");
System.out.println("读取字符数: " + readContent.length());
System.out.println("内容一致性: " + content.equals(readContent.toString()));
}
// 实用的编码检测和转换工具
public static void encodingUtility() {
System.out.println("\n--- 编码检测和转换工具 ---");
// 创建不同编码的测试文件
createTestFiles();
// 检测和转换文件编码
detectAndConvertEncoding();
}
// 创建不同编码的测试文件
private static void createTestFiles() {
String[] contents = {
"UTF-8 encoded file with 中文 characters",
"GBK encoded file with 中文 characters",
"ASCII encoded file with English characters"
};
String[] encodings = {"UTF-8", "GBK", "US-ASCII"};
String[] fileNames = {"utf8_test.txt", "gbk_test.txt", "ascii_test.txt"};
for (int i = 0; i < contents.length; i++) {
try (FileOutputStream fos = new FileOutputStream(fileNames[i]);
OutputStreamWriter osw = new OutputStreamWriter(fos, encodings[i])) {
osw.write(contents[i]);
System.out.println("创建 " + encodings[i] + " 编码文件: " + fileNames[i]);
} catch (IOException e) {
System.err.println("创建文件 " + fileNames[i] + " 时发生错误: " + e.getMessage());
}
}
}
// 检测和转换文件编码
private static void detectAndConvertEncoding() {
String[] fileNames = {"utf8_test.txt", "gbk_test.txt", "ascii_test.txt"};
for (String fileName : fileNames) {
System.out.println("\n检测文件: " + fileName);
// 尝试用不同编码读取
String[] encodings = {"UTF-8", "GBK", "US-ASCII", "ISO-8859-1"};
for (String encoding : encodings) {
try (FileInputStream fis = new FileInputStream(fileName);
InputStreamReader isr = new InputStreamReader(fis, encoding)) {
char[] buffer = new char[1024];
int charsRead = isr.read(buffer);
String content = new String(buffer, 0, charsRead);
// 简单的编码正确性检查
boolean isValid = true;
for (int i = 0; i < charsRead; i++) {
if (buffer[i] == 0xFFFD) { // Unicode替换字符
isValid = false;
break;
}
}
System.out.printf(" %-10s: %s (有效: %s)%n",
encoding,
content.length() > 50 ? content.substring(0, 50) + "..." : content,
isValid);
} catch (Exception e) {
System.out.printf(" %-10s: 读取失败 (%s)%n", encoding, e.getMessage());
}
}
}
}
}
// 高级转换流工具类
class AdvancedStreamConverter {
// 智能编码检测
public static Charset detectEncoding(File file) {
// 常见编码列表
Charset[] commonCharsets = {
StandardCharsets.UTF_8,
Charset.forName("GBK"),
StandardCharsets.ISO_8859_1,
StandardCharsets.US_ASCII
};
for (Charset charset : commonCharsets) {
if (isValidEncoding(file, charset)) {
return charset;
}
}
return StandardCharsets.UTF_8; // 默认返回UTF-8
}
// 验证编码是否有效
private static boolean isValidEncoding(File file, Charset charset) {
try (FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, charset)) {
char[] buffer = new char[1024];
int charsRead = isr.read(buffer);
// 检查是否包含无效字符
for (int i = 0; i < charsRead; i++) {
if (buffer[i] == 0xFFFD) { // Unicode替换字符
return false;
}
}
return true;
} catch (Exception e) {
return false;
}
}
// 转换文件编码
public static void convertFileEncoding(File sourceFile, File targetFile, Charset targetCharset)
throws IOException {
Charset sourceCharset = detectEncoding(sourceFile);
try (FileInputStream fis = new FileInputStream(sourceFile);
InputStreamReader isr = new InputStreamReader(fis, sourceCharset);
BufferedReader br = new BufferedReader(isr);
FileOutputStream fos = new FileOutputStream(targetFile);
OutputStreamWriter osw = new OutputStreamWriter(fos, targetCharset);
BufferedWriter bw = new BufferedWriter(osw)) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
}
}
// 批量转换目录中的文件编码
public static void convertDirectoryEncoding(File sourceDir, File targetDir, Charset targetCharset)
throws IOException {
if (!targetDir.exists()) {
targetDir.mkdirs();
}
File[] files = sourceDir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile()) {
File targetFile = new File(targetDir, file.getName());
convertFileEncoding(file, targetFile, targetCharset);
System.out.println("转换文件: " + file.getName());
} else if (file.isDirectory()) {
File targetSubDir = new File(targetDir, file.getName());
convertDirectoryEncoding(file, targetSubDir, targetCharset);
}
}
}
}
}
// 高级转换流工具使用示例
public class AdvancedConverterExample {
public static void main(String[] args) {
System.out.println("=== 高级转换流工具使用示例 ===");
try {
// 创建测试文件
createTestFiles();
// 智能编码检测
smartEncodingDetection();
// 文件编码转换
fileEncodingConversion();
} catch (IOException e) {
System.err.println("高级转换流示例时发生错误: " + e.getMessage());
}
}
private static void createTestFiles() throws IOException {
System.out.println("\n--- 创建测试文件 ---");
// 创建UTF-8编码文件
try (FileWriter fw = new FileWriter("test_utf8.txt", StandardCharsets.UTF_8)) {
fw.write("UTF-8测试文件\n包含中文字符:你好世界\nEnglish text with special characters: €£¥");
}
// 创建GBK编码文件
try (OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("test_gbk.txt"), "GBK")) {
osw.write("GBK测试文件\n包含中文字符:你好世界\nEnglish text");
}
System.out.println("测试文件创建完成");
}
private static void smartEncodingDetection() {
System.out.println("\n--- 智能编码检测 ---");
String[] testFiles = {"test_utf8.txt", "test_gbk.txt"};
for (String fileName : testFiles) {
File file = new File(fileName);
if (file.exists()) {
Charset detectedCharset = AdvancedStreamConverter.detectEncoding(file);
System.out.println("文件 " + fileName + " 检测到的编码: " + detectedCharset.name());
}
}
}
private static void fileEncodingConversion() throws IOException {
System.out.println("\n--- 文件编码转换 ---");
File sourceFile = new File("test_utf8.txt");
File targetFile = new File("converted_to_gbk.txt");
if (sourceFile.exists()) {
AdvancedStreamConverter.convertFileEncoding(
sourceFile, targetFile, Charset.forName("GBK"));
System.out.println("文件编码转换完成: " + sourceFile.getName() + " -> " + targetFile.getName());
// 验证转换结果
Charset detectedCharset = AdvancedStreamConverter.detectEncoding(targetFile);
System.out.println("转换后文件编码: " + detectedCharset.name());
}
}
}通过本章节的学习,您已经掌握了Java I/O流的核心概念和使用方法,包括字节流与字符流的区别、文件操作、缓冲流和转换流的应用。这些知识是Java程序处理数据输入输出的基础,对于开发各种Java应用程序都非常重要。