Java 8 无法使用java.util.Base64正确编码和解码
将“awid”设为基数为64的12个字符长度的id(Java 8 无法使用java.util.Base64正确编码和解码,java-8,base64,decode,encode,Java 8,Base64,Decode,Encode,将“awid”设为基数为64的12个字符长度的id(A-Z A-Z 0-9“-@”)。这是输入 我的最终目标是在这些awid和UUIDs之间创建一个双射映射,使用一些填充,将awid作为初始输入 在尝试使用java.util.Base64时,在再次解码和编码之后,我没有得到初始值。我犯的愚蠢错误是什么?:) 对于下面我给出的可再现示例,输出是错误的,因为输入字符串在decode()-encode()之后没有返回,并且双射没有保留(Q39s/L和Q39s/a都映射到相同的值) 请毫不犹豫地指出我在
A-Z A-Z 0-9“-@”
)。这是输入
我的最终目标是在这些awid和UUID
s之间创建一个双射映射,使用一些填充,将awid作为初始输入
在尝试使用java.util.Base64
时,在再次解码和编码之后,我没有得到初始值。我犯的愚蠢错误是什么?:)
对于下面我给出的可再现示例,输出是错误的,因为输入字符串在decode()
-encode()
之后没有返回,并且双射没有保留(Q39s/L
和Q39s/a
都映射到相同的值)
请毫不犹豫地指出我在代码中犯的任何其他错误,即使它们与问题没有直接关系。谢谢。如果您将编码数据视为整字节(或ASCII字符)序列,则Base64编码不是所有输入大小的双射映射。Base64将八位的单位编码为六位的单位(每个单位产生64种可能的组合),因此当您编码四个字节时,换句话说
4×8=32
位,您将得到32/6=5⅓代码>单位输出,这意味着输出的第六个单位不会使用所有位
换句话说,当您将由64个已定义字符中的六个组成的任意字符串视为Base64编码时,您将投影一个64的字符串⁶ 组合到具有256个字节的六个字节的“源”序列⁴ 组合,这意味着数据丢失
如果您选择的输入大小可以投影到整数单位,则可以使用Base64编码作为双射映射,例如,显然,六个源字节可以编码为八个Base64编码字节。但它不适用于6个编码字节。有趣的是,它将适用于您实际需要的大小,因为九个源字节将被编码为十二个编码字节:9×8=72
,72/6=12
,。非常感谢。我将把12个编码字符拆分为8+4个字符,这将使我得到6个字节(msb)+3个字节(lsb)。在发布问题后清除我找到的资源(是的,我知道我应该从它开始)
------------------------------------------> Q39s/L (6 [51 33 39 73 2f 4c])
4 [43 7f 6c fc] -> 6 [51 33 39 73 2f 41] -> Q39s/A (6 [51 33 39 73 2f 41])
4 [43 7f 6c fc] -> 6 [51 33 39 73 2f 41] -> Q39s/A (6 [51 33 39 73 2f 41])
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.StringJoiner;
public class StackOverflowQuestion {
public static void main(String[] args) {
String halfAwid = "Q39s/L";
byte[] sigBits = Base64.getDecoder().decode(halfAwid.getBytes(StandardCharsets.UTF_8));
byte[] actualSigBits = Base64.getEncoder().withoutPadding().encode(sigBits);
String actualHalfAwid = new String(actualSigBits, StandardCharsets.UTF_8);
byte[] sigBits2 = Base64.getDecoder().decode(halfAwid.getBytes(StandardCharsets.UTF_8));
byte[] actualSigBits2 = Base64.getEncoder().withoutPadding().encode(sigBits2);
String actualHalfAwid2 = new String(actualSigBits2, StandardCharsets.UTF_8);
System.out.println("----------------------------------------------> "
+ halfAwid + " (" + toHexString(halfAwid) + ") "
+ "\n"
+ " "
+ toHexString(sigBits) + " -> "
+ toHexString(actualSigBits) + " -> "
+ actualHalfAwid + " (" + toHexString(actualHalfAwid) + ") "
+ "\n"
+ " "
+ toHexString(sigBits2) + " -> "
+ toHexString(actualSigBits2) + " -> "
+ actualHalfAwid2 + " (" + toHexString(actualHalfAwid2) + ")"
+ "");
}
private static String toHexString(byte[] bytes) {
StringJoiner joiner = new StringJoiner(" ", "" + bytes.length + " [", "]");
for (byte b : bytes) {
joiner.add(String.format("%02x", b));
}
return joiner.toString();
}
private static String toHexString(String text) {
return toHexString(text.getBytes());
}
}