包含特殊字符(例如?)的Java字符串在每个特殊字符中占用两个字节的大小,但是String length方法或使用从getBytes方法返回的字节数组获取其长度不会返回计数为两个字节的特殊字符。
如何正确计算字符串中的字节数?
例:
单词endere?o应该返回9而不是8。
当我运行System.out.println("endereo".getBytes().length);时,它显示" 9"。
@briarheart哪个Java版本?在Java 7中,我得到了八分。
@briarheart getBytes()使用平台默认编码,可能已经是UTF-8。请参阅:不同平台上的平台默认字符集?
我正在使用Java8。我想" utf-8"是任何版本的Java的默认编码,除非显式覆盖此行为。
定义特殊字符。是什么让您认为它需要两个字节的大小?哪里?您是指char[]中支持String的意思吗?单词endereo应该使我返回9而不是8。为什么?为什么不32?
@briarheart UTF-8不是任何Java版本的默认编码。默认编码通常由操作系统定义,在Linux上通常为UTF-8,但在Windows上很少。
长度在很大程度上取决于编码,例如对于endereo及其ISO-8859-1:8,UTF-8:9,EUC-JP:10,UTF-16BE:16,UTF-32:32
@安德烈亚斯是的,你是对的。即使未指定,我也会看到值为" UTF-8"的" file.encoding"属性。" UTF-8"的显式后备仅存在于java.nio.charset.Charset类的代码中。
我没有得到正确的长度,因为我的默认编码是ISO-8859-1。
同样,定义长度。 String#length()方法具有非常具体的定义。
究竟是哪个定义?
所有Java字符串内部都使用两字节字符。
The word endere?o should return me length 9 instead of 8.
如果您希望长度为8个字符的"endere?o"字符串的大小为9个字节:7个ASCII字符和1个非ASCII字符,那么我想您要使用UTF-8字符集ASCII表中包含的字符为1个字节,其他字符为1个字节。
but String length method or getting the length of it with the byte
array returned from getBytes method doesn't return special chars
counted as two bytes.
String length()方法不能回答以下问题:使用了多少个字节?但是回答:"其中包含多少个" UTF-16代码单元"或更简单的char?"
String length() Javadoc:
Returns the length of this string. The length is equal to the number
of Unicode code units in the string.
没有参数的byte[] getBytes()方法将String编码为字节数组。您可以使用返回数组的length属性来了解编码的String使用了多少字节,但是结果将取决于编码期间使用的字符集。
但是byte[] getBytes()方法不允许指定字符集:它使用平台的默认字符集。
因此,如果底层操作系统默认情况下使用的字符集不是您要用来以字节编码字符串的字符集,则使用它可能无法获得预期的结果。
此外,根据部署应用程序的平台,以字节为单位的字符串编码方式可能会发生变化。这可能是不希望的。
最后,如果无法将字符串编码为默认字符集,则该行为未指定。
因此,应非常谨慎地使用此方法,或者完全不要使用。
byte[] getBytes() Javadoc:
Encodes this String into a sequence of bytes using the platform's
default charset, storing the result into a new byte array.
The behavior of this method when this string cannot be encoded in the
default charset is unspecified. The java.nio.charset.CharsetEncoder
class should be used when more control over the encoding process is
required.
在您的String示例"endere?o"中,如果getBytes()返回一个大小为8而不是9的数组,则意味着您的操作系统默认不使用UTF-8,而是一个字符集使用1字节固定宽度的字符集,例如ISO 8859-1及其派生字符集(例如,基于Windows OS的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:
Encodes this String into a sequence of bytes using the named charset,
storing the result into a new byte array.
The behavior of this method when this string cannot be encoded in the
given charset is unspecified. The java.nio.charset.CharsetEncoder
class should be used when more control over the encoding process is
required.
byte[] java.lang.String.getBytes(Charset charset) Javadoc:
Encodes this String into a sequence of bytes using the given charset,
storing the result into a new byte array.
This method always replaces malformed-input and unmappable-character
sequences with this charset's default replacement byte array. The
java.nio.charset.CharsetEncoder class should be used when more control
over the encoding process is required.
您可以使用一个或另一个(虽然它们之间有一些复杂性)将您的String编码为带有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操作系统的计算机上的输出:
default charset = windows-1252
getBytes() with default charset, size = 8
getBytes("UTF-8"), size = 9
getBytes(StandardCharsets.UTF_8), size = 9
getBytes("UTF-16"), size = 18
getBytes(StandardCharsets.UTF_16), size = 18
"字符串length()方法不能回答以下问题:使用了多少个字节?但是回答:"包含多少个字符?"不,它返回字符串中UTF-16代码单元的数量。可以有多个代码 每个代码点的单位,每个"字素簇"可以有多个代码点(大多数用户会认为一个字符)。
@plugwash从技术上讲,是的,您是正确的。 我想我太庸俗了。 我会更具体一些:"包含多少char?" 我更新了。 感谢您的相关评论:)