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

时间:2017-04-03 22:03:09

标签: java string encoding utf-8

包含ç等特殊字符的 在每个特殊字符中占用两个字节,但是String length method或者使用字节数组获取它的长度从getBytes method返回并不会返回计为两个字节的特殊字符。

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

示例:

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

1 个答案:

答案 0 :(得分:10)

  

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

byte[] getBytes() Javadoc:

  

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

     

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

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

要了解运行应用程序的当前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:

  

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

     

此方法在此字符串无法编码时的行为   鉴于charset未指定。 java.nio.charset.CharsetEncoder   当对编码过程有更多控制时,应该使用class   必需的。

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

  

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

     

此方法始终替换malformed-input和unmappable-character   具有此charset的默认替换字节数组的序列。该   当更多控件时,应该使用java.nio.charset.CharsetEncoder类   编码过程是必需的。

你可以使用一个或另一个(虽然它们之间有一些复杂性)来编码一个字节数组中的字符串 UTF-8 或任何其他字符集,所以得到它的大小具体的charset。

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

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

您可以根据需要获得9个字节的长度。

这是一个更全面的示例,其中显示了默认编码,使用默认字符集平台的字节编码,UTF-8UTF-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操作系统的输出:

  

默认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