2016-03-30 55 views
4

让“awids”为基数为64的12个字符长度的ID(A-Z a-z 0-9 "-" "@")。这是输入。无法使用java.util.Base64正确编码和解码

我最终的目标是在这些awids和UUID之间创建一个双射映射,使用一些填充,将awids作为初始输入。

虽然试图使用java.util.Base64我没有得到解码和编码后的初始值。我做什么愚蠢的错误? :)

随着再现的例子目前我输出下面是错误的,因为后一个decode()输入字符串未得到后面 - encode()和双射不保留(Q39s/LQ39s/A和既映射到相同的值)。

 
    ------------------------------------------>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()); 
     } 
    } 

不要犹豫指向任何其他错误,我在代码做,即使他们不直接相关的问题。谢谢。

回答

2

如果将编码数据视为整个字节(或ASCII字符)的序列,则Base64编码不是所有输入大小的双射映射。 Base64编码的单元为8位到6位的单元(每个单元产生64个可能的组合),所以当你编码4个字节,换句话说4×8=32位时,你将得到32/6=5⅓单位输出,这意味着第六单元输出不会使用所有位。

换句话说,当您将由64个定义的字符中的6个组成的任意字符串视为Base64编码时,您会将64⁶组合的字符串投影到具有256个组合的六个字节的“源”序列,​​这意味着数据丢失。

如果您选择可投影到整个单位数量的输入大小,则可以使用Base64编码作为双射映射。显然六个源字节可以编码为八个Base64编码字节。但它不适用于六个编码字节。有趣的是,它将适用于您实际需要的大小,因为九个源字节将被编码为十二个编码字节:9×8=7272/6=12

+0

你说得对。谢谢。我将12个编码的字符分成8 + 4个字符,这将导致我6字节(msb)+ 3字节(lsb)。 – Costin

+0

我在发布问题后发现了清除的资源(是的,我知道我应该开始使用它)https://en.wikipedia.org/wiki/Base64 – Costin

相关问题