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

Phi*_*ffi 3 java string encoding utf-8

包含特殊字符,如ç需要大小的两个字节中的每个特殊字符,但字符串长度的方法或得到的它的长度与字节数组从返回getBytes方法不返回计数为两个字节特殊字符.

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

例:

这个词endereço应该返回长度为9而不是8.

dav*_*xxx 10

exereço这个词应该让我长9而不是8.

如果你希望"endereço"字符串的大小为9个字节,长度为8个字符:7个ASCII字符,1个不是ASCII字符,我想你要使用字符串,UTF-8它使用1个字节表示ASCII表中包含的字符,以及更多其他.

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


String length()方法没有回答问题:使用了多少字节?但回答:"有多少"UTF-16代码单元"或更简单的chars包含在? "

String length() Javadoc:

返回此字符串的长度.长度等于字符串中Unicode代码单元的数量.


byte[] getBytes()没有参数的方法将String编码为字节数组.您可以使用length返回数组的属性来了解编码String使用的字节数,但结果将取决于编码期间使用的字符集.但该byte[] getBytes()方法不允许指定字符集:它使用平台的默认字符集.
因此,如果底层操作系统默认使用的字符集不是您希望用于以字节为单位对字符串进行编码的字符集,则使用它可能无法提供预期的结果.
此外,根据部署应用程序的平台,字符串以字节为单位编码的方式可能会发生变化.这可能是不受欢迎的.
最后,如果无法在默认字符集中对String进行编码,则行为未指定.
因此,这种方法应该非常谨慎使用或根本不使用.

byte[] getBytes() Javadoc:

使用平台的默认字符集将此String编码为字节序列,将结果存储到新的字节数组中.

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

在String示例中"endereço",如果getBytes()返回一个大小为8而不是9的数组,则表示您的操作系统默认情况下不使用,UTF-8而是使用1个字节固定宽度字符的ISO 8859-1字符集,例如其派生的字符集,例如windows-1252Windows操作系统根据.

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


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

  • byte[] java.lang.String.getBytes(String charsetName) throws UnsupportedEncodingException

  • byte[] java.lang.String.getBytes(Charset charset)

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

byte[] java.lang.String.getBytes(String charsetName) throws UnsupportedEncodingException Javadoc:

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

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

byte[] java.lang.String.getBytes(Charset charset) Javadoc:

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

此方法始终使用此charset的缺省替换字节数组替换格式错误的输入和不可映射的字符序列.当需要更多地控制编码过程时,应该使用java.nio.charset.CharsetEncoder类.

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

例如,UTF-8通过使用获取编码字节数组,getBytes(String charsetName)您可以这样做:

String yourString = "endereço";
byte[] bytes = yourString.getBytes("UTF-8");
int sizeInBytes = bytes.length;
Run Code Online (Sandbox Code Playgroud)

您可以根据需要获得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);
}
Run Code Online (Sandbox Code Playgroud)

我的机器上基于Windows操作系统的输出:

默认charset = windows-1252

getBytes()使用默认字符集,size = 8

getBytes("UTF-8"),size = 9

getBytes(StandardCharsets.UTF_8),size = 9

getBytes("UTF-16"),size = 18

getBytes(StandardCharsets.UTF_16),size = 18