【问题标题】:How to convert binary string to Java String encoded using UFT-8如何将二进制字符串转换为使用 UTF-8 编码的 Java 字符串
【发布时间】:2016-11-12 01:36:53
【问题描述】:

为了从 4 个字的字符串中发送一大块位,我正在从字符串中获取字节数组并计算位串。

StringBuilder binaryStr = new StringBuilder();

byte[] bytesFromStr = str.getBytes("UTF-8");
for (int i = 0, l = bytesFromStr.length; i < l; i++) {
    binaryStr.append(Integer.toBinaryString(bytesFromStr[i]));
}

String result = binaryStr.toString();

当我想做反向操作时出现问题:将位字符串转换为使用UTF-8编码的Java字符串。

请问,有没有人可以向我解释最好的方法?

提前致谢!

【问题讨论】:

  • 我认为这是stackoverflow.com/questions/5499924/…的副本,至少我认为它会有所帮助。
  • 无法逆转该操作。你不可能知道 100011010100110101100100 是 3 个字节,还是 4,或 5,或......你想达到什么目的?你为什么这样做?
  • 如果您有字符串"1a",那么它是由字符1a 构建的,它们被放置在Unicode 表中4997 的位置。在二进制形式中,它们应该表示为01100011100001。但是Integer.toBinaryString(49) 的结果是110001 而不是0110001(忽略前导0)。因此,正如 JB Nizet 指出的那样,无法检测 111 是否代表 1 1 111 11 11111。无论如何,您在这里所做的看起来像XY problem
  • 如果我有 4 个用 UFT-8 编码的字,则意味着我有 4 个字节,如果我没记错的话。在那种情况下,我认为我可以扭转操作。这是关于隐写术和数据泄露的 PoC。
  • "如果我有 4 个用 UFT-8 编码的单词意味着我有 4 个字节"你为什么这么认为?你能给我们指出一些给你这个想法的资源吗?您所说的可以解释为“utf-8 在一个字节上写入一个字”,但请尝试考虑一下有多少字,以及字节可以容纳多少个数字。

标签: java string utf-8 binary byte


【解决方案1】:

TL;DR 不要使用toBinaryString()。见最后解决方案。


您的问题是 Integer.toBinaryString() 不返回前导零,例如

System.out.println(Integer.toBinaryString(1));   // prints: 1
System.out.println(Integer.toBinaryString(10));  // prints: 1010
System.out.println(Integer.toBinaryString(100)); // prints: 1100100

出于您的目的,您希望始终为每个字节获取 8 位。

您还需要防止负值导致错误,例如

System.out.println(Integer.toBinaryString((byte)129)); // prints: 11111111111111111111111110000001

最简单的方法是这样的:

Integer.toBinaryString((b & 0xFF) | 0x100).substring(1)

首先,它将字节 b 强制转换为 int,然后只保留低 8 位,最后设置第 9 位,例如129(十进制)变为1 1000 0001(二进制,为清楚起见添加了空格)。然后它会排除第 9 位,实际上确保前导零就位。

最好将它作为辅助方法:

private static String toBinary(byte b) {
    return Integer.toBinaryString((b & 0xFF) | 0x100).substring(1);
}

在这种情况下,您的代码变为:

StringBuilder binaryStr = new StringBuilder();
for (byte b : str.getBytes("UTF-8"))
    binaryStr.append(toBinary(b));
String result = binaryStr.toString();

例如如果str = "Hello World",你会得到:

0100100001100101011011000110110001101111001000000101011101101111011100100110110001100100

你当然可以自己做,不用toBinaryString()

StringBuilder binaryStr = new StringBuilder();
for (byte b : str.getBytes("UTF-8"))
    for (int i = 7; i >= 0; i--)
        binaryStr.append((b >> i) & 1);
String result = binaryStr.toString();

那可能也会跑得更快。

【讨论】:

  • 谢谢@Andreas。我将对您的实现进行一些测试,避免使用“toBinaryString()”并尝试恢复信息。
【解决方案2】:

感谢@Andreas 提供您的代码。我使用你的函数测试并再次“解码”为 UTF-8:

StringBuilder revealStr = new StringBuilder();
for (int i = 0; i < result.length(); i += 8) {
    revealStr.append((char) Integer.parseUnsignedInt(result.substring(i, i + 8), 2));
} 

感谢所有帮助我的人。

【讨论】:

    猜你喜欢
    • 2017-06-14
    • 2016-10-01
    • 2012-01-09
    • 2011-08-16
    • 2018-05-24
    • 2011-12-08
    • 2011-05-20
    • 1970-01-01
    相关资源
    最近更新 更多