如何对十六进制字符串进行base-64编码
How to base-64 encode a hex string
我正在尝试对十六进制字符串进行 base-64 编码(复制在下方),但我从 Java8 调用中获得的编码为 base64 的值与我在不同的在线转换器上获得的值不匹配。我想弄清楚我遗漏了哪些步骤(或我正在采取的错误步骤):
//hexString is 07050600030102
Base64.getEncoder().encodeToString(hexString.getBytes(StandardCharsets.UTF_8));
//output I am getting from Java8 ic copied below:
MDcwNTA2MDAwMzAxMDI=
//online converters:
BwUGAAMBAg==
这不符合您的预期:
hexString.getBytes(StandardCharsets.UTF_8)
这只是将十六进制字符串编码为 UTF-8 - 您想要 解析 十六进制字符串,以便每对十六进制数字最终成为一个字节。 base64 结果不同的事实只是因为您使用 base64 编码的字节不同。
要将十六进制字符串解析为字节,您可以使用 Guava(在其他库中)
byte[] bytes = BaseEncoding.base16().decode(hexString);
String base64 = BaseEncoding.base64().encode(bytes);
Jon 的回答是正确的,但我想我会尝试以不同的方式解释它。我认为 encoding/decoding 有时会让人有些困惑。
当您说您的数据被编码为 "hex string" 时,该数据被编码为 "pretty printable"。事实上,如果要打印,"hex encoding" 是您可以对任何二进制数据执行的最简单的操作。使用十六进制编码,没有二进制数据是不可打印的(在我们知道的计算机系统上)!
为了更清楚,假设有人给你一个 "hex encoded" 字符串 a9
(这个想法与你的 07050600030102
相同)。这意味着当将某个字节流解释为十六进制字符时,它变成 a9
。由于每个十六进制字符:[0-9][a-f]
可以编码为半字节 0000
到 1111
,您可以将实际位解码为:1010 1001
(为简洁起见,使用空白) .所以,十六进制编码为 a9
的实际上是一个字节 10101001
。
所以,如果你现在 "base64-encode" 它,你应该使用 10101001
作为输入!就字节数组而言,这将是:{-87}
因为 -87
是 Java.[=38 中整数值的二进制补码表示中位序列 10101001
的十进制值=]
当您执行以下操作时:hexString.getBytes(StandardCharsets.UTF_8)
或 hexString.getBytes()
(如果您计算机上的默认字符集为 UTF-8
),那么您将获得 hexString
根据 UTF-8
编码进行解释,并且由于该编码向后兼容 ASCII 编码,您将得到一个 2 字节数组,其第一个字节是十进制 97
(或二进制01100001
)表示字符'a'
,第二个字节为十进制57
,(或二进制00111001
)表示字符'9'
(十进制的9)。因此,您将从 getBytes()
调用中获得的字节数组是:{97, 57}
.
如您所见,这两者是两个不同的东西。您想要对数组 {-87}
表示的字节进行 base64 编码,但最终得到数组 {97, 57}
.
表示的 base64 编码字节
我正在尝试对十六进制字符串进行 base-64 编码(复制在下方),但我从 Java8 调用中获得的编码为 base64 的值与我在不同的在线转换器上获得的值不匹配。我想弄清楚我遗漏了哪些步骤(或我正在采取的错误步骤):
//hexString is 07050600030102
Base64.getEncoder().encodeToString(hexString.getBytes(StandardCharsets.UTF_8));
//output I am getting from Java8 ic copied below:
MDcwNTA2MDAwMzAxMDI=
//online converters:
BwUGAAMBAg==
这不符合您的预期:
hexString.getBytes(StandardCharsets.UTF_8)
这只是将十六进制字符串编码为 UTF-8 - 您想要 解析 十六进制字符串,以便每对十六进制数字最终成为一个字节。 base64 结果不同的事实只是因为您使用 base64 编码的字节不同。
要将十六进制字符串解析为字节,您可以使用 Guava(在其他库中)
byte[] bytes = BaseEncoding.base16().decode(hexString);
String base64 = BaseEncoding.base64().encode(bytes);
Jon 的回答是正确的,但我想我会尝试以不同的方式解释它。我认为 encoding/decoding 有时会让人有些困惑。
当您说您的数据被编码为 "hex string" 时,该数据被编码为 "pretty printable"。事实上,如果要打印,"hex encoding" 是您可以对任何二进制数据执行的最简单的操作。使用十六进制编码,没有二进制数据是不可打印的(在我们知道的计算机系统上)!
为了更清楚,假设有人给你一个 "hex encoded" 字符串 a9
(这个想法与你的 07050600030102
相同)。这意味着当将某个字节流解释为十六进制字符时,它变成 a9
。由于每个十六进制字符:[0-9][a-f]
可以编码为半字节 0000
到 1111
,您可以将实际位解码为:1010 1001
(为简洁起见,使用空白) .所以,十六进制编码为 a9
的实际上是一个字节 10101001
。
所以,如果你现在 "base64-encode" 它,你应该使用 10101001
作为输入!就字节数组而言,这将是:{-87}
因为 -87
是 Java.[=38 中整数值的二进制补码表示中位序列 10101001
的十进制值=]
当您执行以下操作时:hexString.getBytes(StandardCharsets.UTF_8)
或 hexString.getBytes()
(如果您计算机上的默认字符集为 UTF-8
),那么您将获得 hexString
根据 UTF-8
编码进行解释,并且由于该编码向后兼容 ASCII 编码,您将得到一个 2 字节数组,其第一个字节是十进制 97
(或二进制01100001
)表示字符'a'
,第二个字节为十进制57
,(或二进制00111001
)表示字符'9'
(十进制的9)。因此,您将从 getBytes()
调用中获得的字节数组是:{97, 57}
.
如您所见,这两者是两个不同的东西。您想要对数组 {-87}
表示的字节进行 base64 编码,但最终得到数组 {97, 57}
.