【问题标题】:byte to string and vice versa字节到字符串,反之亦然
【发布时间】:2012-03-06 15:02:06
【问题描述】:

我需要转换一个随机生成的盐值并将其存储在数据库中。为了将其存储在数据库中,我将其转换为字符串。然后为了检索原始值,我将其转换回字节。但是两个值都不匹配。我试过“UTF-8”、“UTF-16”、BASE64Encoder。

SecureRandom ranGen = new SecureRandom();
byte[] aesKey = new byte[16]; // 16 bytes = 128 bits
ranGen.nextBytes(aesKey);   
System.out.println(aesKey);

String a=new String(aesKey,"UTF-16");
byte[] b=new byte[16];
b=a.getBytes("UTF-16");
System.out.println(b);

上述代码的输出(执行2次):

[B@11563ff
[B@1581593

[B@170888e
[B@11563ff

【问题讨论】:

  • 两个系统输出的输出是什么?
  • 正如我在回答中所说,您在这里打印的是 Object toString 输出,默认情况下是 getClass().getName() + "@" + Integer.toHexString(hashCode() )。因此,由于您有两个不同的字节数组(即不同的对象),因此输出是不同的。
  • 正如 DaveJohnston 所暗示的,在 java 语言中使用 toString() 时应该小心。

标签: java encoding character-encoding bytearray


【解决方案1】:

您真的应该使用Base64 将二进制数据转换为字符串。有很多免费的实现可用,例如在Apache Commons Codec 中找到的那个。

另外,它真的很容易使用,例如:

对于编码:

import org.apache.commons.codec.binary.Base64;
...
byte[] abValue = {...}; // Your data to encode
Base64 base64 = new Base64();
String strEncodedData = base64.encodeToString(abValue).trim();

解码:

import org.apache.commons.codec.binary.Base64;
...
String strEncodedData = "..."; // Your previously encoded data
Base64 base64 = new Base64();
byte[] abValue = base64.decode(strValue);

【讨论】:

  • 我在 java 中对 Base64 的导入语句应该是什么
  • 已编辑以包含包含 ;-)。您还需要将公共编解码器 jar 添加到项目库中。
【解决方案2】:

正如上面编写的代码,打印aesKey,然后打印b,您实际打印的是数组对象的toString 方法的输出,这只是默认的Object toString 方法。所以我不明白你怎么能期望它们是一样的。

如果你真的想检查它们是否相同,你应该逐字节比较它们。

就您关于将 byte[] 作为字符串存储在数据库中的实际问题而言,最好的办法是对其进行 Base64 编码。我建议为此使用 Apache Commons Codec 库。请参阅user guide

编辑:

使用您提到的 BASE64Encode 和 BASE64Decoder,代码如下:

    SecureRandom ranGen = new SecureRandom();
    byte[] aesKey = new byte[16]; // 16 bytes = 128 bits
    ranGen.nextBytes(aesKey);
    String a = new BASE64Encoder().encode(aesKey);

    System.out.println(a);

    byte[] b = new BASE64Decoder().decodeBuffer(a);
    System.out.println(new BASE64Encoder().encode(b));

    for (int i = 0; i < aesKey.length; i++) {
        System.out.println(aesKey[i] + " " + b[i]);
    }

在这里,我还单独循环了字节,以表明它们确实是相等的。

【讨论】:

  • 如果我错了,请纠正我。如果两个字节在任何意义上都相等。那么他们即使是默认对象 toString 也应该给出相同的值。
  • 它们是字节数组,而且不是同一个对象,所以默认的toString方法不会返回相同的结果。
  • 那么是返回他们的对象地址吗,
  • 正在写:getClass().getName() + "@" + Integer.toHexString(hashCode())
  • Object中的hashCode方法是native的,据我所知并不是Object在内存中的确切地址,而是与之相关的东西。
猜你喜欢
  • 2011-05-18
  • 1970-01-01
  • 2011-07-02
  • 2014-04-16
  • 2015-12-09
  • 2014-11-18
  • 1970-01-01
  • 1970-01-01
  • 2012-11-11
相关资源
最近更新 更多