杰瑞科技汇

Java文件GBK转UTF8,如何操作?

核心思想

转换文件编码的核心步骤如下:

Java文件GBK转UTF8,如何操作?-图1
(图片来源网络,侵删)
  1. 以源编码(GBK)读取文件内容,将其读入内存中(通常是 Stringbyte[])。
  2. 以目标编码(UTF-8)将内容写入新文件

使用 Java 原生 I/O (不推荐,但有助于理解原理)

这种方法使用 InputStreamReaderOutputStreamWriter,它们是处理字符流和字节流之间编码转换的核心类。

缺点

  • 代码相对冗长。
  • 需要手动处理资源关闭(使用 try-finally),容易出错。
  • 对于大文件,一次性读取到内存中可能导致 OutOfMemoryError
import java.io.*;
import java.nio.charset.StandardCharsets;
public class GbkToUtf8Native {
    public static void convert(String sourceFilePath, String targetFilePath) {
        // 1. 使用 GBK 编码读取源文件
        // 2. 使用 UTF-8 编码写入目标文件
        try (
            // 使用 try-with-resources 自动关闭资源
            InputStreamReader isr = new InputStreamReader(new FileInputStream(sourceFilePath), "GBK");
            BufferedReader br = new BufferedReader(isr);
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(targetFilePath), StandardCharsets.UTF_8);
            BufferedWriter bw = new BufferedWriter(osw)
        ) {
            String line;
            // 逐行读取,避免内存溢出
            while ((line = br.readLine()) != null) {
                bw.write(line);
                // 写入换行符,因为 readLine() 会消耗掉换行符
                bw.newLine(); 
            }
            System.out.println("文件转换成功: " + sourceFilePath + " -> " + targetFilePath);
        } catch (UnsupportedEncodingException e) {
            System.err.println("不支持的编码格式: " + e.getMessage());
        } catch (FileNotFoundException e) {
            System.err.println("文件未找到: " + e.getMessage());
        } catch (IOException e) {
            System.err.println("发生IO异常: " + e.getMessage());
        }
    }
    public static void main(String[] args) {
        String sourceFile = "source_gbk.txt";      // 假设这是一个GBK编码的文件
        String targetFile = "target_utf8.txt";    // 这是将要生成的UTF-8编码的文件
        // 为了演示,我们先创建一个GBK编码的测试文件
        createGbkFile(sourceFile);
        convert(sourceFile, targetFile);
    }
    // 辅助方法:创建一个GBK编码的测试文件
    private static void createGbkFile(String filePath) {
        try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), "GBK")) {
            osw.write("你好,世界!\n");
            osw.write("This is a test file.\n");
            osw.write("GBK to UTF-8 conversion.\n");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用 Java NIO (推荐,更现代的方式)

Java NIO (New I/O) 提供了更高效、更灵活的文件操作方式。Files 类的 readAllLineswrite 方法可以极大地简化代码。

优点

Java文件GBK转UTF8,如何操作?-图2
(图片来源网络,侵删)
  • 代码简洁。
  • Files.readAllLines 会自动处理字符编码。
  • 同样使用 try-with-resources 管理资源。

注意Files.readAllLines 会将整个文件内容读入内存,因此不适合处理非常大的文件,对于大文件,应使用 Files.lines() 方法(见方法三)。

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class GbkToUtf8Nio {
    public static void convert(String sourceFilePath, String targetFilePath) {
        Path sourcePath = Paths.get(sourceFilePath);
        Path targetPath = Paths.get(targetFilePath);
        try {
            // 1. 以 GBK 编码读取所有行到 List<String>
            List<String> lines = Files.readAllLines(sourcePath, Charset.forName("GBK"));
            // 2. 以 UTF-8 编码将所有行写入新文件
            // StandardCharsets.UTF_8 是一个预定义的常量,比 "UTF-8" 字符串更高效
            Files.write(targetPath, lines, StandardCharsets.UTF_8);
            System.out.println("文件转换成功: " + sourceFilePath + " -> " + targetFilePath);
        } catch (IOException e) {
            System.err.println("文件转换失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        String sourceFile = "source_gbk.txt";
        String targetFile = "target_utf8_nio.txt";
        createGbkFile(sourceFile); // 复用上面方法一的辅助方法
        convert(sourceFile, targetFile);
    }
    // 辅助方法同上...
    private static void createGbkFile(String filePath) { /* ... */ }
}

使用 Java NIO 流式处理 (最佳实践,适用于大文件)

如果文件非常大(例如几百MB或GB),使用 readAllLines 会导致内存溢出,应该使用 Files.lines() 方法,它会返回一个 Stream<String>,我们可以逐行处理并写入新文件,这是最节省内存的方式。

优点

  • 内存效率极高,适合处理任意大小的文件。
  • 代码依然很简洁。
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class GbkToUtf8NioStream {
    public static void convert(String sourceFilePath, String targetFilePath) {
        Path sourcePath = Paths.get(sourceFilePath);
        Path targetPath = Paths.get(targetFilePath);
        // 使用 try-with-resources 确保 Stream 和 BufferedWriter 都被正确关闭
        try (
            // 1. 以 GBK 编码创建一个行流
            Stream<String> lines = Files.lines(sourcePath, Charset.forName("GBK"));
            // 2. 以 UTF-8 编码创建一个缓冲写入器
            BufferedWriter writer = Files.newBufferedWriter(targetPath, StandardCharsets.UTF_8)
        ) {
            // 3. 逐行处理并写入
            // forEach 会保持流的顺序,非常适合此场景
            lines.forEach(line -> {
                try {
                    writer.write(line);
                    writer.newLine(); // 写入换行符
                } catch (IOException e) {
                    // 将受检异常转为非受检异常,以便 Stream 的 forEach 能处理
                    throw new RuntimeException("写入文件时发生错误", e);
                }
            });
            System.out.println("大文件转换成功: " + sourceFilePath + " -> " + targetFilePath);
        } catch (IOException e) {
            System.err.println("文件转换失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        String sourceFile = "source_gbk.txt";
        String targetFile = "target_utf8_nio_stream.txt";
        createGbkFile(sourceFile); // 复用上面方法一的辅助方法
        convert(sourceFile, targetFile);
    }
    // 辅助方法同上...
    private static void createGbkFile(String filePath) { /* ... */ }
}

使用 Apache Commons IO (最健壮、最推荐的方式)

如果你的项目已经引入了 Apache Commons IO 库,或者你想要一个经过充分测试、功能更强大的工具,IOUtils 是最佳选择。

Java文件GBK转UTF8,如何操作?-图3
(图片来源网络,侵删)

添加 Maven 依赖:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version> <!-- 请使用最新版本 -->
</dependency>

优点

  • 代码极其简洁。
  • 底层已经处理了各种边界情况和资源管理,非常健壮。
  • IOUtils.copy() 方法可以自动处理缓冲,效率很高。
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class GbkToUtf8CommonsIo {
    public static void convert(String sourceFilePath, String targetFilePath) {
        try (
            // 以 GBK 编码创建输入流
            FileInputStream fis = new FileInputStream(sourceFilePath);
            InputStreamReader isr = new InputStreamReader(fis, "GBK");
            // 以 UTF-8 编码创建输出流
            FileOutputStream fos = new FileOutputStream(targetFilePath);
            OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
        ) {
            // 一行代码搞定复制和编码转换
            IOUtils.copy(isr, osw);
            System.out.println("文件转换成功 (使用 Commons IO): " + sourceFilePath + " -> " + targetFilePath);
        } catch (IOException e) {
            System.err.println("文件转换失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        String sourceFile = "source_gbk.txt";
        String targetFile = "target_utf8_commons_io.txt";
        createGbkFile(sourceFile); // 复用上面方法一的辅助方法
        convert(sourceFile, targetFile);
    }
    // 辅助方法同上...
    private static void createGbkFile(String filePath) { /* ... */ }
}

总结与建议

方法 优点 缺点 适用场景
原生 I/O 原理清晰,无需额外库 代码冗长,易出错 学习原理,简单脚本
Java NIO (readAllLines) 代码简洁,现代API 内存占用高,不适合大文件 中小文件,追求代码简洁
Java NIO (lines) 内存占用极低,代码简洁 略比 readAllLines 复杂一点 大文件处理的首选,通用性最强
Apache Commons IO 代码最简洁,最健壮,功能强大 需要引入第三方库 生产环境推荐,特别是已有项目依赖

推荐选择

  • 新项目/生产环境:优先选择 方法三 (Java NIO 流式处理)方法四 (Apache Commons IO),方法三更“原生”,方法四更“省心”。
  • 快速脚本/学习:可以使用 方法二 (Java NIO readAllLines),但要确保文件不大。
  • 理解底层:可以看看 方法一 (原生 I/O) 的实现。
分享:
扫描分享到社交APP
上一篇
下一篇