杰瑞科技汇

Java String转byte,编码如何选?

最简单、最直接的方法:String.getBytes()

这是 Java String 类自带的最直接的方法,它会使用平台的默认字符编码Charset.defaultCharset())将字符串转换为字节数组。

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

语法

byte[] bytes = str.getBytes();

示例

public class StringToByteExample {
    public static void main(String[] args) {
        String str = "Hello, 世界!";
        // 使用默认字符编码
        byte[] bytes = str.getBytes();
        System.out.println("原始字符串: " + str);
        System.out.println("字节数组长度: " + bytes.length);
        System.out.println("字节数组内容: " + Arrays.toString(bytes));
        // 尝试将字节数组转换回字符串(使用相同的默认编码)
        String decodedStr = new String(bytes);
        System.out.println("解码后的字符串: " + decodedStr);
    }
}

⚠️ 重要警告:不推荐在生产环境中使用

这种方法的最大问题是可移植性差,你的代码在一台机器上(比如中文 Windows 系统,默认可能是 GBK 编码)运行正常,但在另一台机器上(比如英文 Linux 系统,默认可能是 UTF-8 编码)就可能产生乱码。

仅用于个人测试或确定所有运行环境都使用相同默认编码的场景。强烈不推荐用于需要跨平台部署的应用程序。


推荐方法:指定字符编码

为了确保代码的可移植性和正确性,你应该始终显式地指定字符编码,Java 提供了多种方式来指定编码。

String.getBytes(String charsetName)

使用字符集的名称(如 "UTF-8", "GBK")来指定编码。

Java String转byte,编码如何选?-图2
(图片来源网络,侵删)
String str = "Hello, 世界!";
// 使用 UTF-8 编码(强烈推荐)
byte[] utf8Bytes = str.getBytes("UTF-8");
System.out.println("UTF-8 字节数组: " + Arrays.toString(utf8Bytes)); // 长度为 13
// 使用 GBK 编码
byte[] gbkBytes = str.getBytes("GBK");
System.out.println("GBK 字节数组: " + Arrays.toString(gbkBytes)); // 长度为 10

String.getBytes(Charset charset) (更现代、更安全)

这是 Java 1.5 引入的方法,使用 java.nio.charset.Charset 对象,这种方式更安全,因为它可以避免因编码名称拼写错误而导致的 UnsupportedEncodingException

import java.nio.charset.StandardCharsets; // Java 7+ 引入的常量类,非常方便
String str = "Hello, 世界!";
// 使用 StandardCharsets.UTF-8 (推荐)
byte[] utf8Bytes = str.getBytes(StandardCharsets.UTF_8);
System.out.println("UTF-8 字节数组: " + Arrays.toString(utf8Bytes));
// 也可以使用 Charset.forName() (不推荐,因为它会抛出异常)
// try {
//     byte[] bytes = str.getBytes(Charset.forName("UTF-8"));
// } catch (UnsupportedEncodingException e) {
//     e.printStackTrace();
// }

StandardCharsets 是 Java 7 引入的,它提供了一系列预定义的字符集常量(如 UTF_8, ISO_8859_1, US_ASCII),是硬编码编码名称的最佳实践。


完整的最佳实践示例

下面是一个完整的、健壮的示例,展示了如何正确地编码和解码字符串。

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class StringToByteBestPractice {
    public static void main(String[] args) {
        String originalString = "你好, Java!";
        // --- 编码:String -> byte[] ---
        // 1. 选择一个标准编码,UTF-8 是目前最广泛使用的推荐选择
        String charsetName = StandardCharsets.UTF_8.name();
        // 2. 使用 getBytes(Charset) 方法进行编码
        byte[] byteArray = originalString.getBytes(StandardCharsets.UTF_8);
        System.out.println("原始字符串: " + originalString);
        System.out.println("使用的编码: " + StandardCharsets.UTF_8);
        System.out.println("转换后的字节数组: " + Arrays.toString(byteArray));
        System.out.println("字节数组长度: " + byteArray.length);
        // --- 解码:byte[] -> String ---
        // 1. 使用相同的编码将字节数组转换回字符串
        String decodedString = new String(byteArray, StandardCharsets.UTF_8);
        System.out.println("\n解码后的字符串: " + decodedString);
        System.out.println("解码后是否与原始字符串相等: " + originalString.equals(decodedString));
    }
}

常见字符编码简介

编码名称 描述 适用场景
UTF-8 Unicode 的可变长度编码方式,可以表示地球上几乎所有字符,是 Web 和现代应用的国际标准。 强烈推荐,所有新项目都应使用 UTF-8 作为默认编码。
GBK / GB2312 中国国家标准编码,主要用于简体中文,在中国大陆的一些旧系统或特定软件中可能还会遇到。 处理中国大陆遗留系统时可能需要。
ISO-8859-1 Latin-1 编码,它只能表示西欧语言中的字符,一个重要特性是:它不会造成数据丢失,任何字节序列都可以被它解释成字符。 在不确定编码时,有时会先用它作为“无损”的中间编码进行转换。
US-ASCII 7位编码,是 ASCII 的超集,只能表示英文字母、数字和一些符号。 处理纯英文文本。

常见问题与解决方案

Q1: 为什么我得到的字节数组长度和预期不一样?

A: 这是因为字符编码的变长特性,UTF-8 编码中:

Java String转byte,编码如何选?-图3
(图片来源网络,侵删)
  • 英文字母(如 'A', '1')占用 1 个字节。
  • 中文字符(如 '中', '国')通常占用 3 个字节。

所以字符串 "A中" 在 UTF-8 下的长度是 1 + 3 = 4

Q2: 我从网络或文件中读取了一串字节,如何转换成 String

A: 使用 new String(byte[], charset) 构造函数。关键在于你必须知道这串字节当初是用什么编码生成的

// 假设你从网络接收到的原始字节是用 GBK 编码的
byte[] receivedBytes = {-60, -29, -43, -71}; // 这是 "你好" 的 GBK 编码
// 如果你用错误的编码(如 UTF-8)去解码,就会得到乱码
String wrongString = new String(receivedBytes, StandardCharsets.UTF_8);
System.out.println("用 UTF-8 解码 (乱码): " + wrongString); // 输出: ???
// 必须用正确的编码(GBK)去解码
String correctString = new String(receivedBytes, "GBK");
System.out.println("用 GBK 解码 (正确): " + correctString); // 输出: 你好

Q3: 如何处理“UnsupportedEncodingException”?

A: 如果你使用的是 String.getBytes(String charsetName),并且传入了一个不存在的编码名称,就会抛出这个异常。

现代 Java 开发中,你应该优先使用 StandardCharsets,它里面的编码都是 Java 虚拟机支持的,所以不会抛出 UnsupportedEncodingException,代码更简洁、安全。

如果必须使用字符串形式的编码名称,最好用 try-catch 包裹起来:

try {
    byte[] bytes = "test".getBytes("My-Unkown-Charset");
} catch (UnsupportedEncodingException e) {
    System.err.println("不支持的编码: " + e.getMessage());
    // 可以在这里记录日志或采取其他恢复措施
}
场景 推荐方法 原因
新项目 / 跨平台应用 str.getBytes(StandardCharsets.UTF_8) 可移植性好,支持全球所有字符,是业界标准。
与旧系统集成(如GBK) str.getBytes("GBK")str.getBytes(Charset.forName("GBK")) 必须匹配对方系统的编码才能正确解析。
快速测试 / 个人脚本 str.getBytes() 简单,但仅在确定环境一致时使用。
解码网络/文件数据 new String(byteArray, StandardCharsets.UTF_8) 必须知道原始编码,UTF-8 是最常见的默认选择。

核心要点:永远不要依赖默认编码,始终显式指定编码,首选 StandardCharsets.UTF_8

分享:
扫描分享到社交APP
上一篇
下一篇