Java中的Base64编码与C中的HttpServerUtility.UrlTokenEncode

Java中的Base64编码与C中的HttpServerUtility.UrlTokenEncode,java,c#,base64,encode,httpserverutility,Java,C#,Base64,Encode,Httpserverutility,我在尝试用Java编码字符串时遇到了问题 我在C中有以下代码,字符串Bpz2Gjg01d7VfGfD8ZP1UA==,当我执行C代码时,我得到: QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT090 首先,我尝试用Java复制前面的代码 尝试使用javax.xml.bind.DatatypeConverter类: 但是我得到了下面的字符串 与C字符串相比,缺少最后一个零: QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT09 在第二次尝试中,我使用了BouncyCast

我在尝试用Java编码字符串时遇到了问题

我在C中有以下代码,字符串Bpz2Gjg01d7VfGfD8ZP1UA==,当我执行C代码时,我得到:

QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT090

首先,我尝试用Java复制前面的代码 尝试使用javax.xml.bind.DatatypeConverter类:

但是我得到了下面的字符串 与C字符串相比,缺少最后一个零:

QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT09

在第二次尝试中,我使用了BouncyCastle Base64编码器:

但我得到的是和前面的一模一样的字符串 仍然缺少最后一个零:

QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT09


有人知道会发生什么吗?

我已经看过了.NET framework代码。UrlTokenEncode实际上从base64字符串的末尾删除了任何额外的=padding符号,并将它们替换为padding符号的数量,因此可以是0、1或2。这就是导致字符串末尾出现额外0的原因。因此请注意:HttpServerUtility.UrlTokenEncode方法不是普通的Base64编码器。它实际上在内部使用Convert.ToBase64String进行常规编码,并在顶部添加了更多内容请参阅我对该问题的评论。如果需要创建这个精确的字符串,则需要在常规base64编码的基础上在Java中实现相同的更改。

我根据对我的评论找到了一个解决方案,基本上我在

然后我把C代码翻译成Java代码,看起来是这样的:

public static String UrlTokenEncode(byte[] input) {
     try {
         if (input == null) {
         return null;
         }

         if (input.length < 1) {
             return null;
         }

         String base64Str = null;
         int endPos = 0;
         char[] base64Chars = null;

         base64Str = Base64.toBase64String(input);
         if (base64Str == null) {
             return null;
         }

         for (endPos = base64Str.length(); endPos > 0; endPos--) {
             if (base64Str.charAt(endPos - 1) != '=') {
                 break;
             }
         }

         base64Chars = new char[endPos + 1];
         base64Chars[endPos] = (char) ((int) '0' + base64Str.length() - endPos);
         for (int iter = 0; iter < endPos; iter++) {
             char c = base64Str.charAt(iter);
              switch (c) {
                 case '+':
                     base64Chars[iter] = '-';
                     break;
                 case '/':
                     base64Chars[iter] = '_';
                     break;
                 case '=':
                     base64Chars[iter] = c;
                 break;
                 default:
                     base64Chars[iter] = c;
                 break;
             }
          }
         return new String(base64Chars);
     } catch (Exception e) {
         return null;
     }
}
M2NIclh4eEwxRGp2MEsyeFc0SHVDZz090


您正在使用的c方法可能使用base64 url编码。有多种base64编码类型,base64 url编码不同于默认的base64编码。如果要使用base64编码,请尝试Java8中的base64 form java.util。此外,UrlTokenEncode方法对常规base64编码中的符号字符进行一些映射,以便可以安全地在URL中使用它们,也就是说,它将+替换为-和/替换为64。如果您需要Java中的确切功能,这种映射也是必要的。但是,这不适用于您的情况。此外,如果您使用标准的.NET Convert.ToBase64Stringencbuff方法,它将不会在末尾包含额外的0,因此与Java等效方法相同。看起来UrlTokenEncode方法出于某种原因正在添加它。非常感谢您的评论,它们起到了指导作用。
public static void main(String[] args) {
    String strWord = "Bpz2Gjg01d7VfGfD8ZP1UA==";
    byte[] encbuff = strWord.getBytes(StandardCharsets.UTF_8);
    String strWordEncoded = DatatypeConverter.printBase64Binary(encbuff);
    System.out.println(strWordEncoded);
}
public static void main(String[] args) {
   String strWord = "Bpz2Gjg01d7VfGfD8ZP1UA==";
   byte[] encbuff = strWord.getBytes(StandardCharsets.UTF_8);
   String strWordEncoded = new String(Base64.encode(encbuff));
   System.out.println(strWordEncoded);
}
public static String UrlTokenEncode(byte[] input) {
     try {
         if (input == null) {
         return null;
         }

         if (input.length < 1) {
             return null;
         }

         String base64Str = null;
         int endPos = 0;
         char[] base64Chars = null;

         base64Str = Base64.toBase64String(input);
         if (base64Str == null) {
             return null;
         }

         for (endPos = base64Str.length(); endPos > 0; endPos--) {
             if (base64Str.charAt(endPos - 1) != '=') {
                 break;
             }
         }

         base64Chars = new char[endPos + 1];
         base64Chars[endPos] = (char) ((int) '0' + base64Str.length() - endPos);
         for (int iter = 0; iter < endPos; iter++) {
             char c = base64Str.charAt(iter);
              switch (c) {
                 case '+':
                     base64Chars[iter] = '-';
                     break;
                 case '/':
                     base64Chars[iter] = '_';
                     break;
                 case '=':
                     base64Chars[iter] = c;
                 break;
                 default:
                     base64Chars[iter] = c;
                 break;
             }
          }
         return new String(base64Chars);
     } catch (Exception e) {
         return null;
     }
}
public static void main(String[] args) {
   String strWord = "Bpz2Gjg01d7VfGfD8ZP1UA==";
   byte[] encbuff = strWord.getBytes(StandardCharsets.UTF_8);
   String strWordEncoded = UrlTokenEncode(encbuff);
}