Java 如何正确计算字符串字节数?

Java 如何正确计算字符串字节数?,java,string,encoding,utf-8,Java,String,Encoding,Utf 8,包含特殊字符(如ç的字符串)的字符串在每个特殊字符中占用两个字节的大小,但使用从返回的字节数组获取字符串的长度不会返回计为两个字节的特殊字符 如何正确计算字符串中的字节数 示例: 单词endereço应该返回长度9而不是8 单词endereço应该返回长度为9而不是8的我 如果您希望长度为8个字符的“endereço”字符串的大小为9个字节:7个ASCII字符和1个非ASCII字符,我假设您希望使用UTF-8字符集,该字符集对ASCII表中包含的字符使用1个字节,对其他字符使用更多字节 但是字符

包含特殊字符(如
ç
的字符串)的字符串在每个特殊字符中占用两个字节的大小,但使用从返回的字节数组获取字符串的长度不会返回计为两个字节的特殊字符

如何正确计算字符串中的字节数

示例:

单词
endereço
应该返回长度9而不是8

单词endereço应该返回长度为9而不是8的我

如果您希望长度为8个字符的
“endereço”
字符串的大小为9个字节:7个
ASCII
字符和1个非
ASCII
字符,我假设您希望使用
UTF-8
字符集,该字符集对ASCII表中包含的字符使用1个字节,对其他字符使用更多字节

但是字符串长度方法或用字节获取它的长度 从getBytes方法返回的数组不返回特殊字符 计算为两个字节


String
length()
方法没有回答以下问题:使用了多少字节?而是回答:其中包含多少“UTF-16代码单元”或更简单的
char
s?

String
length()
Javadoc:

返回此字符串的长度。长度等于数字 字符串中Unicode代码单位的数目


不带参数的
byte[]
getBytes()
方法将字符串编码到字节数组中。您可以使用返回数组的
length
属性来了解编码字符串使用了多少字节,但结果将取决于编码过程中使用的字符集。 但是
byte[]
getBytes()
方法不允许指定字符集:它使用平台的默认字符集
因此,如果底层操作系统在默认情况下使用的字符集不是您希望用于将字符串编码为字节的字符集,那么使用它可能不会得到预期的结果
此外,根据部署应用程序的平台,字符串的字节编码方式可能会发生变化。这可能是不可取的
最后,如果字符串不能在默认字符集中编码,则行为未指定。
因此,使用这种方法时要非常小心,否则就不要使用

byte[]
getBytes()
Javadoc:

使用平台的 默认字符集,将结果存储到新的字节数组中

当此字符串无法在中编码时,此方法的行为 默认字符集未指定。java.nio.charset.CharsetEncoder 当需要对编码过程进行更多控制时,应使用类 必需的

在字符串示例
“endereço”
中,如果
getBytes()
返回一个大小为8而不是9的数组,这意味着您的操作系统默认情况下不使用
UTF-8
,而是使用1字节固定宽度的字符集,如
ISO 8859-1
,以及基于windows操作系统的衍生字符集,如
windows-1252

要知道应用程序运行的当前Java虚拟机的默认字符集,可以使用以下实用程序方法:
charset defaultCharset=charset.defaultCharset()


解决方案

byte[]
getBytes()
方法附带两个非常有用的重载:

  • byte[]java.lang.String.getBytes(String charsetName)引发不支持的编码异常

  • byte[]java.lang.String.getBytes(字符集字符集)

与没有参数的
getBytes()
方法相反,这些方法允许指定字节编码期间要使用的字符集

byte[]java.lang.String.getBytes(String charsetName)抛出不支持的编码异常
Javadoc:

使用命名字符集将此字符串编码为字节序列, 将结果存储到新的字节数组中

当此字符串无法在中编码时,此方法的行为 给定的字符集未指定。java.nio.charset.CharsetEncoder 当需要对编码过程进行更多控制时,应使用类 必需的

byte[]java.lang.String.getBytes(字符集字符集)
Javadoc:

使用给定的字符集将此字符串编码为字节序列, 将结果存储到新的字节数组中

此方法始终替换格式错误的输入和不可映射的字符 具有此字符集的默认替换字节数组的序列。这个 当需要更多控制时,应使用java.nio.charset.CharsetEncoder类 在整个编码过程中是必需的

您可以使用一个或另一个(虽然它们之间有一些复杂之处)在字节数组中使用UTF-8或任何其他字符集对字符串进行编码,从而获得该特定字符集的大小

例如,要使用
getBytes(String charsetName)
获得一个
UTF-8
编码字节数组,可以执行以下操作:

String yourString = "endereço";
byte[] bytes = yourString.getBytes("UTF-8");
int sizeInBytes = bytes.length;
您将获得9个字节的长度,如您所愿。

下面是一个显示默认编码的更全面的示例,使用默认字符集平台进行字节编码,
UTF-8
UTF-16

public static void main(String[] args) throws UnsupportedEncodingException {

    // default charset
    Charset defaultCharset = Charset.defaultCharset();
    System.out.println("default charset = " + defaultCharset);

    // String sample
    String yourString = "endereço";

    //  getBytes() with default platform encoding
    System.out.println("getBytes() with default charset, size = " + yourString.getBytes().length + System.lineSeparator());

    // getBytes() with specific charset UTF-8
    System.out.println("getBytes(\"UTF-8\"), size = " + yourString.getBytes("UTF-8").length);       
    System.out.println("getBytes(StandardCharsets.UTF_8), size = " + yourString.getBytes(StandardCharsets.UTF_8).length + System.lineSeparator());

    // getBytes() with specific charset UTF-16      
    System.out.println("getBytes(\"UTF-16\"), size = " + yourString.getBytes("UTF-16").length);     
    System.out.println("getBytes(StandardCharsets.UTF_16), size = " + yourString.getBytes(StandardCharsets.UTF_16).length);
}
基于Windows操作系统的计算机上的输出:

默认字符集=windows-1252

具有默认字符集的getBytes(),大小为8

getBytes(“UTF-8”),大小=9

getBytes(StandardCharsets.UTF_8),大小=9

getBytes(“UTF-16”),大小=18

getBytes(StandardCharsets.UTF_16),大小=18


当我运行
System.out.println(“endereço”.getBytes().length”)时它打印“9”。@briarheart哪个版本的Java?在Java7中,我是