有一个String变量,包含ascii字符和双字节字符(例如,Chinese,Japanese,...)。
如何确定String的总长度?另外,我想用字符串substring / replace函数实现。
答案 0 :(得分:6)
Java中的字符串类型隐式为UTF-16。所有其他编码(例如UTF-8)应使用byte
数组表示。
“长度”是一个含糊不清的术语。
每个Unicode代码点将使用一个或两个代码单位(16位char
s) - 基本多语言平面和补充范围。当转码为不同的编码时,字符串将消耗的字节数可以改变。一系列代码点也可以组合在一起形成一个用户可见的字形。
所以,这里有一些方法来衡量一个字符串的“长度”:
我在a blog post中介绍了部分内容。
评论:是否有一种简单的方法/ API来处理混合字节字符串? (剪切/缩短/ substring()字符串,如“sDDsssDDDDsDD”(s:单 字节ascii字符,DD:双字节字符)?
考虑Java字符串文字"Hello 您好世界"
,也可以表示为"Hello \u60a8\u597d\u4e16\u754c"
。
这可以在传统的Windows Simplified Chinese双字节编码中编码为字节序列:
48 65 6c 6c 6f 20 c4 fa ba c3 ca c0 bd e7
为了将其转换为Java字符,您需要对其进行解码:
byte[] data = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, (byte) 0xc4,
(byte) 0xfa, (byte) 0xba, (byte) 0xc3, (byte) 0xca, (byte) 0xc0,
(byte) 0xbd, (byte) 0xe7 };
Charset encoding = Charset.forName("x-mswin-936");
String hello = new String(data, encoding);
现在您已将数据转码为Unicode,您可以使用常用的字符串操作机制(substring,regex matching等)。
请注意,您必须知道转换前使用的双字节编码。如果你不知道编码,你所拥有的只是垃圾。
我不知道Android支持哪些编码,但您可以通过调用Charset.availableCharsets()在运行时发现这一点。如果Android不支持您需要的编码,请查看ICU4J库。
答案 1 :(得分:4)
Java字符串是字符,而不是字节。长度是字符数。如果需要字节数,请使用
str.getBytes(encoding).length
其中编码例如是“UTF-8”。
答案 2 :(得分:4)
正如其他人所说,Java Strings是概念上只读的Java字符数组,String的“长度”是字符数。但是,有一些复杂的问题:
Java角色不一定是您认为的角色。特别是,可以使用Java字符表示更多的Unicode字符(代码点)。某些Unicode代码点需要两个Java字符来表示它们。 (这是Thilo所指的“扩展平面”问题。)
某些JVM(启动时设置了相应的JVM标志)将使用字符串表示,其中字符以UTF-8编码。虽然String的长度是相同的(在这种情况下,UTF-8表示的Java字符数),但使用的内存可能会少得多。
然后有一个问题是需要多少字节才能将字符串的字符表示为UTF-8或其他一些编码。据我所知,唯一能找到答案的JVM就是进行转换;例如使用getBytes(charSet)
。
最后,问题是String在堆中占用了多少字节。您可以找出String
对象及其关联的char[]
支持对象中有多少字节。但是,当您考虑substring
和其他String
方法可以创建共享单个支持数组的字符串集时,预测将会发生什么可能会非常棘手。< / p>
答案 3 :(得分:0)
Java在内部使用Unicode,因此实际字符是什么并不重要。 String.length()
会给你正确的长度。其他String方法也是如此。