【问题标题】:Confusion with string.getBytes()与 string.getBytes() 混淆
【发布时间】:2015-05-27 08:30:22
【问题描述】:

我有一个由 BSON 序列化的字节数组 byteObj

String strObj = new String(byteObj)
System.out.println(byteObj.length)
System.out.println(strObj.getBytes().length)

结果是152154。而且这两个字节数组是不一样的。如何从字符串中恢复原始的 bson 字节数组?

更新:

152 154
[-104, 0, 0, 0, 4, 116, 105, 116, 108, 101, 0, 80, 0, 0, 0, 2, 48, 0, 5, 0, 0, 0, 116, 104, 105, 115, 0, 2, 49, 0, 3, 0, 0, 0, 105, 115, 0, 2, 50, 0, 2, 0, 0, 0, 97, 0, 2, 51, 0, 5, 0, 0, 0, 116, 104, 105, 115, 0, 2, 52, 0, 2, 0, 0, 0, 97, 0, 2, 53, 0, 3, 0, 0, 0, 105, 115, 0, 2, 54, 0, 6, 0, 0, 0, 116, 105, 116, 108, 101, 0, 0, 4, 99, 111, 110, 116, 101, 110, 116, 0, 51, 0, 0, 0, 2, 48, 0, 5, 0, 0, 0, 116, 104, 105, 115, 0, 2, 49, 0, 2, 0, 0, 0, 97, 0, 2, 50, 0, 8, 0, 0, 0, 99, 111, 110, 116, 101, 110, 116, 0, 2, 51, 0, 3, 0, 0, 0, 105, 115, 0, 0, 0]
[-17, -65, -67, 0, 0, 0, 4, 116, 105, 116, 108, 101, 0, 80, 0, 0, 0, 2, 48, 0, 5, 0, 0, 0, 116, 104, 105, 115, 0, 2, 49, 0, 3, 0, 0, 0, 105, 115, 0, 2, 50, 0, 2, 0, 0, 0, 97, 0, 2, 51, 0, 5, 0, 0, 0, 116, 104, 105, 115, 0, 2, 52, 0, 2, 0, 0, 0, 97, 0, 2, 53, 0, 3, 0, 0, 0, 105, 115, 0, 2, 54, 0, 6, 0, 0, 0, 116, 105, 116, 108, 101, 0, 0, 4, 99, 111, 110, 116, 101, 110, 116, 0, 51, 0, 0, 0, 2, 48, 0, 5, 0, 0, 0, 116, 104, 105, 115, 0, 2, 49, 0, 2, 0, 0, 0, 97, 0, 2, 50, 0, 8, 0, 0, 0, 99, 111, 110, 116, 101, 110, 116, 0, 2, 51, 0, 3, 0, 0, 0, 105, 115, 0, 0, 0]

首先是 BSON 字节数组。

更新 2: 测试代码

    BSONObject ob = new BasicBSONObject()
            .append("title", Arrays.asList(new String[]{"this", "is", "a", "this", "a", "is", "title"}))
            .append("content", Arrays.asList(new String[]{"this", "a", "content", "is"}));


    byte[] ahaha = BSON.encode(ob);
    BSON.decode(ahaha);

    // BSON.decode(new String(ahaha).getBytes());

    byte[] strByte = new String(ahaha).getBytes();

    System.out.println(ahaha.length + "\t" + strByte.length);
    System.out.println(Arrays.toString(ahaha));
    System.out.println(Arrays.toString(strByte));

二进制数据转换为字符串,反之亦然的解决方案见How do you convert binary data to Strings and back in Java?

【问题讨论】:

  • 你原来的 byteObj 数组的长度应该是 154...
  • 你确定你的字节数组是文本吗?我的意思是,也许 Byte 数组是一个图像,并且字节不能转换为 String 中的有效字符:这就是长度不同的原因。
  • 投反对票有什么理由吗?你连这个问题都看懂了吗?
  • 不,如果字节数组的大小是一些,比如说小于130,这两个是一样的,当大于某​​个阈值时,它会失败。
  • 你能以某种方式发布字节数组吗?只是一个猜测:也许这是字节顺序标记的问题。我觉得开头是U+FEFF

标签: java mongodb bson


【解决方案1】:

差异的原因是字节到字符串的转换。请注意,第一个字节是负数。这是Javadoc的解释:

新字符串的长度是字符集的函数,因此可能不等于字节数组的长度。 当给定字节在默认字符集中无效时,此构造函数的行为未指定。

当需要对解码过程进行更多控制时,应使用 CharsetDecoder 类。

【讨论】:

  • 字符串的长度不是问题。他打印出strObj.getBytes().length,这意味着字节的长度,而不是字符数。他希望(和我一样)结果应该与构造String 所给出的字节数组的长度相同。如果未指定,则两种转换都使用默认字符集。
  • 如果我在文档中读到这样的内容,我不会期待任何东西:当此字符串无法以默认字符集编码时,此方法的行为未指定。
  • 我认为序列化形式和charset之间没有任何联系,所以这个CharsetDecoder也不能保证字节数组的一致性。
  • 这就是问题所在。 BSON.encode() 的输出是二进制数据,而不是用默认字符集编码的文本,这是 new String(byte[] b) 期望的输入。这两种编码和解码方法不能一起使用,并且您会遇到编码错误,这就是 Javadoc 警告您的内容。如果要解码 BSON 编码的字节序列,则需要使用 BSON.decode 之类的东西。
  • MongoDB/BSON/String 转换是一个完全不同的问题。您最终可能会使用第三方解决方案或编写自己的解决方案。但很明显,String(byte[])String.getBytes() 将不起作用。它们根本不适用于此类问题。
【解决方案2】:

我无法重现该问题。以下代码返回相同的长度(152)并且字节相同:

byte[] bs = {-104, 0, 0, 0, 4, 116, 105, 116, 108, 101, 0, 80, 0, 0, 0, 2, 48, 0, 5, 0, 0, 0, 116, 104, 105, 115, 0, 2, 49, 0, 3, 0, 0, 0, 105, 115, 0, 2, 50, 0, 2, 0, 0, 0, 97, 0, 2, 51, 0, 5, 0, 0, 0, 116, 104, 105, 115, 0, 2, 52, 0, 2, 0, 0, 0, 97, 0, 2, 53, 0, 3, 0, 0, 0, 105, 115, 0, 2, 54, 0, 6, 0, 0, 0, 116, 105, 116, 108, 101, 0, 0, 4, 99, 111, 110, 116, 101, 110, 116, 0, 51, 0, 0, 0, 2, 48, 0, 5, 0, 0, 0, 116, 104, 105, 115, 0, 2, 49, 0, 2, 0, 0, 0, 97, 0, 2, 50, 0, 8, 0, 0, 0, 99, 111, 110, 116, 101, 110, 116, 0, 2, 51, 0, 3, 0, 0, 0, 105, 115, 0, 0, 0};

System.out.println(new String(bs).getBytes().length);
System.out.println(bs.length);

【讨论】:

  • 我更新了代码。您可能需要 mongo db java 驱动程序才能使其工作。
  • 我只是复制/粘贴你的新代码。结果对我来说是正确的! 152 152[-104, 0, ...][-104, 0, ...]我用的是BSON 2.3版
  • 你能告诉我你的工作环境吗?我在 Ubuntu 12 上使用 mongo db 驱动程序 3.0.1。
  • 还要检查你的语言环境,这样你就知道String(byte[]) 的编码是什么。
  • @romfret:你的默认字符集是什么?您可以使用以下代码获取它:System.out.println(Charset.defaultCharset().displayName());UTF-8 的大小不同,但使用 windows-1252 时的字节数相同。
猜你喜欢
  • 2014-07-09
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多