杰瑞科技汇

Java String转byte数组如何正确编码?

  1. 选择一个字符编码:UTF-8, GBK, ISO-8859-1 等,这个编码决定了字符串中的每个字符(如 'A', '中')会被转换成哪几个字节。
  2. 使用 String 类的 getBytes() 方法:根据你选择的编码,将字符串转换成字节数组。

下面我们详细讲解几种主要的方式,并指出它们的最佳实践和注意事项。

Java String转byte数组如何正确编码?-图1
(图片来源网络,侵删)

核心方法:String.getBytes()

String 类提供了两个重载的 getBytes() 方法,这是实现转换的关键。

getBytes(String charsetName)

这是最推荐、最规范的方法,它允许你明确指定要使用的字符编码。

语法:

byte[] bytes = yourString.getBytes("charsetName");

示例:

Java String转byte数组如何正确编码?-图2
(图片来源网络,侵删)
public class StringToBytesExample {
    public static void main(String[] args) {
        String str = "Hello, 世界!";
        try {
            // 1. 使用 UTF-8 编码(最常用,推荐)
            // 'H' -> 72, 'e' -> 101, ' ' -> 32, '世' -> -28, -72, -83, '界' -> -27, -101, -67
            byte[] utf8Bytes = str.getBytes("UTF-8");
            System.out.println("UTF-8 字节数组: " + Arrays.toString(utf8Bytes));
            // 2. 使用 GBK 编码(中文环境常用)
            byte[] gbkBytes = str.getBytes("GBK");
            System.out.println("GBK 字节数组: " + Arrays.toString(gbkBytes));
            // 3. 使用 ISO-8859-1 编码(仅支持单字节字符,中文会乱码)
            byte[] isoBytes = str.getBytes("ISO-8859-1");
            System.out.println("ISO-8859-1 字节数组: " + Arrays.toString(isoBytes));
        } catch (UnsupportedEncodingException e) {
            // 如果系统不支持指定的编码,会抛出此异常
            // 对于标准编码如 UTF-8, GBK, ISO-8859-1,通常不会发生
            e.printStackTrace();
        }
    }
}

输出:

UTF-8 字节数组: [72, 101, 108, 108, 111, 44, 32, -28, -72, -83, -27, -101, -67, 33]
GBK 字节数组: [72, 101, 108, 108, 111, 44, 32, -42, -48, -50, -60, 33]
ISO-8859-1 字节数组: [72, 101, 108, 108, 111, 44, 32, 63, 63, 33]

注意: 在 ISO-8859-1 编码下,中文字符 '世界' 被转换成了 6363,也就是问号 ,这是因为 ISO-8859-1 (Latin-1) 字符集不包含中文字符,无法表示,所以用 替换。


getBytes()

这个方法不带任何参数,它的行为取决于 Java 虚拟机的默认字符编码。

语法:

Java String转byte数组如何正确编码?-图3
(图片来源网络,侵删)
byte[] bytes = yourString.getBytes();

示例:

public class StringToBytesDefaultExample {
    public static void main(String[] args) {
        String str = "Hello, 世界!";
        // 使用 JVM 默认的字符编码
        byte[] defaultBytes = str.getBytes();
        System.out.println("默认编码的字节数组: " + Arrays.toString(defaultBytes));
    }
}

⚠️ 重要警告:强烈不推荐使用此方法!

为什么? 因为 JVM 的默认编码是依赖于操作系统和运行环境的,这会导致同一个 Java 程序在不同机器上运行时,产生不同的结果,造成难以排查的 bug。

  • 在中文版的 Windows 上,默认编码可能是 GBK
  • 在大多数 Linux 或 macOS 系统上,默认编码是 UTF-8
  • 在英文版的 Windows 上,默认编码可能是 CP1252

最佳实践:永远不要使用无参的 getBytes() 方法。 始终显式地指定一个编码,通常是 "UTF-8"


反向操作:byte 数组转 String

为了完整性,了解如何将 byte 数组转回 String 也同样重要,这能帮助你更好地理解编码和解码的过程。

同样,核心方法是 String 的构造函数:new String(byte[] bytes, String charsetName)

示例:

public class BytesToStringExample {
    public static void main(String[] args) {
        String originalStr = "Hello, 世界!";
        try {
            // 1. 将字符串编码为 UTF-8 字节数组
            byte[] utf8Bytes = originalStr.getBytes("UTF-8");
            System.out.println("原始字节数组 (UTF-8): " + Arrays.toString(utf8Bytes));
            // 2. 使用相同的编码 (UTF-8) 将字节数组解码回字符串
            String decodedFromUtf8 = new String(utf8Bytes, "UTF-8");
            System.out.println("从 UTF-8 解码后的字符串: " + decodedFromUtf8);
            System.out.println("解码是否正确: " + originalStr.equals(decodedFromUtf8)); // true
            System.out.println("--------------------");
            // 3. 使用错误的编码解码(会产生乱码)
            // 用 GBK 的编码去解析一个 UTF-8 的字节数组
            String wrongDecoded = new String(utf8Bytes, "GBK");
            System.out.println("用 GBK 解码 UTF-8 字节数组: " + wrongDecoded);
            System.out.println("解码是否正确: " + originalStr.equals(wrongDecoded)); // false
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}

输出:

原始字节数组 (UTF-8): [72, 101, 108, 108, 111, 44, 32, -28, -72, -83, -27, -101, -67, 33]
从 UTF-8 解码后的字符串: Hello, 世界!
解码是否正确: true
--------------------
用 GBK 解码 UTF-8 字节数组: Hello, �浢獥! (或类似的乱码)
解码是否正确: false

这个例子清晰地展示了:编码和解码必须使用相同的字符集,否则结果就是乱码


  1. 总是使用带编码参数的方法

    • 编码 (String -> byte[]): str.getBytes("UTF-8")
    • 解码 (byte[] -> String): new String(byteArray, "UTF-8")
  2. 首选 UTF-8 编码

    • 通用性:UTF-8 是互联网上最广泛使用的编码,可以表示地球上几乎所有的字符。
    • 兼容性:对于英文字符,UTF-8 的编码结果与 ASCII 和 ISO-8859-1 完全相同,向后兼容性好。
    • 效率:对于英文为主的文本,UTF-8 比固定宽度的 UTF-16(Java 内部使用的编码)更节省空间。
  3. 避免使用无参的 getBytes()

    • 为了代码的可移植性和健壮性,永远不要依赖 JVM 的默认编码,显式指定 "UTF-8" 是最安全、最现代的做法。
  4. 处理 UnsupportedEncodingException

    • 虽然对于标准编码如 "UTF-8""GBK" 等在主流 JVM 上几乎不会抛出此异常,但为了代码的健壮性,使用 try-catch 块是好的习惯,从 Java 7 开始,你还可以使用 StandardCharsets 类来避免这个异常。

使用 StandardCharsets (Java 7+)

Java 7 引入了 java.nio.charset.StandardCharsets 类,它提供了一些常用编码的常量对象,这样做的好处是,getBytes()String 构造函数的重载版本接收 Charset 对象,而不会抛出 UnsupportedEncodingException,使代码更简洁、更安全。

示例:

import java.nio.charset.StandardCharsets;
public class StringToBytesModernExample {
    public static void main(String[] args) {
        String str = "Hello, 世界!";
        // 推荐的现代写法,无需 try-catch
        byte[] utf8Bytes = str.getBytes(StandardCharsets.UTF_8);
        System.out.println("使用 StandardCharsets.UTF_8: " + Arrays.toString(utf
分享:
扫描分享到社交APP
上一篇
下一篇