首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 字元集編碼與轉碼完全指南:從原理到實用工具類

     編輯:Java 相關知識

Java 編譯時會依指定或系統預設編碼將原始檔轉為 Unicode 載入記憶體。運行時處理文字檔、網路傳輸、資料庫交互時,編碼轉換更是家常便飯。本文梳理核心原理,並提供一個功能完備的 EncodingToolkit 工具類,涵蓋字串、檔案、輸入流的編碼轉換與讀寫。

核心原理速覽

  • 編碼:字元 → 位元組序列(String.getBytes(charset))
  • 解碼:位元組序列 → 字元(new String(bytes, charset))
  • 轉碼:源編碼解碼為 Unicode → 目標編碼編碼為位元組

Java 內部統一使用 UTF-16 (char),所有 I/O 操作需透過 Reader/Writer 或 InputStreamReader/OutputStreamWriter 指定編碼。

EncodingToolkit 核心功能

1. 字串重新編碼

// 指定源編碼與目標編碼
public static String reEncoding(String text, String srcEnc, String destEnc)

// 以平台預設編碼讀取字串,轉為目標編碼
public static String reEncoding(String text, String destEnc)

2. 檔案轉碼(流式處理,記憶體友善)

public static boolean reEncoding(File srcFile, String srcEnc,
                                 File destFile, String destEnc)

使用 64KB 字元緩衝區分塊讀寫,適合大檔案。

3. 檔案讀為 Unicode 字串(保留換行格式)

public static String file2String(File file, String encoding)
public static String stream2String(InputStream in, String encoding)

採用 LineNumberReader 逐行讀取,自動補上系統行分隔符。

4. 字串寫入指定編碼檔案

public static boolean string2TextFile(String text, File destFile, String encoding)

自動建立父目錄。

完整原始碼

package lavasoft.common;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.*;

public class EncodingToolkit {
    private static Log log = LogFactory.getLog(EncodingToolkit.class);

    public static void main(String[] args) {
        String han = "漢";
        System.out.println("---------");
    }

    // 字串轉碼:指定源編碼
    public static String reEncoding(String text, String resEncoding, String newEncoding) {
        String rs = null;
        try {
            rs = new String(text.getBytes(resEncoding), newEncoding);
        } catch (UnsupportedEncodingException e) {
            log.error("不支援的字元編碼: " + resEncoding);
            throw new RuntimeException(e);
        }
        return rs;
    }

    // 字串轉碼:預設源編碼
    public static String reEncoding(String text, String newEncoding) {
        String rs = null;
        try {
            rs = new String(text.getBytes(), newEncoding);
        } catch (UnsupportedEncodingException e) {
            log.error("不支援的字元編碼: " + newEncoding);
            throw new RuntimeException(e);
        }
        return rs;
    }

    // 檔案轉碼
    public static boolean reEncoding(File resFile, String resEncoding,
                                     File distFile, String newEncoding) {
        boolean flag = true;
        InputStreamReader reader = null;
        OutputStreamWriter writer = null;
        try {
            reader = new InputStreamReader(new FileInputStream(resFile), resEncoding);
            writer = new OutputStreamWriter(new FileOutputStream(distFile), newEncoding);
            char[] buf = new char[1024 * 64];
            int len;
            while ((len = reader.read(buf)) != -1) {
                writer.write(buf, 0, len);
            }
            writer.flush();
        } catch (FileNotFoundException e) {
            flag = false;
            log.error("檔案不存在");
            throw new RuntimeException(e);
        } catch (IOException e) {
            flag = false;
            log.error("讀寫異常");
            throw new RuntimeException(e);
        } finally {
            closeQuietly(reader);
            closeQuietly(writer);
        }
        return flag;
    }

    // 檔案讀為字串
    public static String file2String(File resFile, String encoding) {
        StringBuffer sb = new StringBuffer();
        try {
            LineNumberReader reader = new LineNumberReader(
                new BufferedReader(new InputStreamReader(new FileInputStream(resFile), encoding)));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line).append(System.getProperty("line.separator"));
            }
            reader.close();
        } catch (UnsupportedEncodingException e) {
            log.error("不支援的編碼: " + encoding);
            throw new RuntimeException(e);
        } catch (FileNotFoundException e) {
            log.error("檔案不存在: " + resFile);
            throw new RuntimeException(e);
        } catch (IOException e) {
            log.error("讀取異常");
            throw new RuntimeException(e);
        }
        return sb.toString();
    }

    // 輸入流讀為字串
    public static String stream2String(InputStream in, String encoding) {
        StringBuffer sb = new StringBuffer();
        LineNumberReader reader = null;
        try {
            reader = new LineNumberReader(
                new BufferedReader(new InputStreamReader(in, encoding)));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line).append(System.getProperty("line.separator"));
            }
        } catch (UnsupportedEncodingException e) {
            log.error("不支援的編碼: " + encoding);
            throw new RuntimeException(e);
        } catch (IOException e) {
            log.error("讀取異常");
            throw new RuntimeException(e);
        } finally {
            closeQuietly(reader);
            closeQuietly(in);
        }
        return sb.toString();
    }

    // 字串寫檔
    public static boolean string2TextFile(String text, File distFile, String encoding) {
        boolean flag = true;
        if (!distFile.getParentFile().exists()) distFile.getParentFile().mkdirs();
        OutputStreamWriter writer = null;
        try {
            writer = new OutputStreamWriter(new FileOutputStream(distFile), encoding);
            writer.write(text);
        } catch (IOException e) {
            flag = false;
            log.error("寫入異常");
            throw new RuntimeException(e);
        } finally {
            closeQuietly(writer);
        }
        return flag;
    }

    private static void closeQuietly(Closeable c) {
        if (c != null) try { c.close(); } catch (IOException ignore) {}
    }
}

使用建議

  • 網路傳輸、資料庫交互明確指定 UTF-8,避免平台預設編碼差異。
  • 大檔案轉碼務必使用流式 API(reEncoding(File, File)),避免 OOM。
  • 日誌記錄編碼異常時包含檔案路徑與編碼名,利於排查。

結語

掌握編碼/解碼原理,配合健壯的工具類,即可從容應對中文亂碼、跨平台部署、舊系統遷移等實戰挑戰。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved