2

有一个包含 ascii 字符和双字节字符的 String 变量(例如,中文、日文、...)。

如何确定 String 的总长度?另外,我想用字符串 substring/replace 函数来实现。

4

4 回答 4

6

Java 中的字符串类型是隐含的 UTF-16。所有其他编码(例如 UTF-8)都应该使用byte数组来表示。

“长度”是一个模棱两可的术语。

每个 Unicode 代码点将使用一个或两个代码单元(16 位char)——基本的多语言平面和补充范围。当转码为不同的编码时,字符串将消耗的字节数可能会发生变化。一系列代码点也可以组合形成一个用户可见的字素。

因此,以下是测量字符串“长度”的方法:

我在一篇博文中介绍了其中的一些内容。


评论:是否有一种简单的方法/API 来处理混合字节字符串?(要剪切/缩短/子字符串()像“sDDsssDDDDsDD”这样的字符串(s:单字节ascii字符,DD:双字节字符)?

考虑 Java 字符串文字"Hello 您好世界",它也可以表示为"Hello \u60a8\u597d\u4e16\u754c".

这可以在传统的 Windows简体中文双字节编码中编码为字节序列:

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,您可以使用通常的字符串操作机制(子字符串正则表达式匹配等)。

请注意,您必须知道在转换之前使用的双字节编码。如果您不知道编码,那么您所拥有的就是垃圾。

我不知道 Android 支持哪些编码,但您可以通过调用Charset.availableCharsets()在运行时发现这一点。如果 Android 不支持您需要的编码,请查看ICU4J库。

于 2012-06-14T09:36:33.973 回答
4

Java 字符串是字符,而不是字节。长度是字符数。如果您想要字节数,请使用

str.getBytes(encoding).length

其中编码是例如“UTF-8”。

于 2012-06-14T09:14:53.657 回答
4

正如其他人所说,Java字符串在概念上是Java字符的只读数组,字符串的“长度”是字符数。但是,有一些复杂的问题:

  • Java 字符不一定是您认为的字符。特别是,Unicode 字符(代码点)比使用 Java 字符表示的要多。一些 Unicode 代码点需要两个 Java 字符来表示它们。(这是 Thilo 所指的“扩展平面”问题。)

  • 一些 JVM(在启动时设置了适当的 JVM 标志)将使用字符串表示,其中字符以 UTF-8 编码。虽然 String 的长度相同(在本例中为 UTF-8 表示的 Java 字符数),但使用的内存可以显着减少。

然后是需要多少字节才能将字符串的字符表示为 UTF-8 或其他编码的问题。据我所知,JVM 提供的唯一方法是进行转换;例如使用getBytes(charSet).

最后,还有一个字符串在堆中占用多少字节的问题。String您可以找出对象及其关联的char[]支持对象中有多少字节。但是,当您考虑到该方法substring和其他String方法可以创建共享单个支持数组的字符串集时,预测这将是什么可能会很棘手。

于 2012-06-14T09:36:50.017 回答
0

Java 在内部使用 Unicode,因此实际字符是什么并不重要。String.length()会给你正确的长度。其他 String 方法也是如此。

于 2012-06-14T09:14:32.937 回答