【问题标题】:getBytes("UCS-2") returns different results in different devices with different API levelsgetBytes("UCS-2") 在不同 API 级别的不同设备中返回不同的结果
【发布时间】:2018-06-06 10:41:42
【问题描述】:

目前我对以下代码有疑问:

String a = "0932300090";
byte[] b = a.getBytes(Charset.forName("UCS-2"));
Log.d("MTINH",Arrays.toString(b));

这段代码已经在两种不同的设备上使用过,一种运行Android 8.0,另一种运行Android 8.1,我得到了两种不同的结果:

在 Android 8.0 中:

-1, -2, 48, 0, 57, 0, 51, 0, 50, 0, 51, 0, 48, 0, 48, 0, 48, 0, 57, 0, 48, 0

在 Android 8.1 中:

-2, -1, 0, 48, 0, 57, 0, 51, 0, 50, 0, 51, 0, 48, 0, 48, 0, 48, 0, 57, 0, 48

似乎结果是成对交换的:[-1 -2] vs [-2 -1]... [48 0] vs [0 48]。

那么这里的问题是什么? Java 或 Android 有什么变化吗?

【问题讨论】:

  • 似乎是字节序问题。
  • @MinasMina 是的,这个问题与 ByteOrder LITTLE_ENDIAN & BIG_ENDIAN 有关
  • 前两个字节是一个字节顺序标记(BOM),它指定了字节序。因此,即使字节流不同,对于接收方来说也不应该是问题。

标签: android string byte android-8.1-oreo


【解决方案1】:

UCS-2 编码Android 8.x 和 9.0 上实际上是 UTF-16。在 Android 8.1 上,android 工程对 UTF-16 编码进行了以下更改。

请注意,BOM 标记 (-2, -1) 包含在输出中。如果您需要跨设备的一致结果,您可以选择使用 UTF-16BE。以下是行为变化的详细信息。

UTF-16 字符集输出字节顺序

UTF-16 字符集(通过java.nio.charset.Charset.forName("UTF-16")java.nio.charset.StandardCharsets.UTF_16 获得)现在使用字节顺序标记将字符串编码为big-endian UTF-16 字节,正如javadoc 所说的那样。 以前,它使用字节顺序标记编码为 little-endian,这与文档相矛盾。

这也改变了在字符串上调用getBytes("UTF-16") 的结果。 这对使用 UTF-16 字符集对字符串进行编码和解码的代码没有影响,因为解码遵循字节顺序标记。它只影响使用 UTF-16 字符集进行编码的代码,然后假定生成的字节是小端序的,例如通过使用忽略字节顺序标记的机制对它们进行解码。

想要使用字节顺序标记编码为 little-endian 的用户可以使用 x-UTF-16LE-BOM 字符集。 (请注意,此字符集不应用于解码字节,除非已知它们是 little-endian。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    • 2015-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多