Java 中的 Base64 编码与 C# 中的 HttpServerUtility.UrlTokenEncode
Base64 Encoding in Java vs HttpServerUtility.UrlTokenEncode in C#
我在尝试对 Java 中的 String
进行编码时遇到了问题。
我在 C# 中有以下代码,当我执行 C# 代码时,string
Bpz2Gjg01d7VfGfD8ZP1UA==得到:
QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT090
public static void Main(string[] args)
{
string strWord = "Bpz2Gjg01d7VfGfD8ZP1UA==";
byte[] encbuff = Encoding.UTF8.GetBytes(strWord);
string strWordEncoded = HttpServerUtility.UrlTokenEncode(encbuff);
Console.WriteLine(strWordEncoded);
}
我试图在第一个中复制 Java 中的先前代码
尝试我使用 javax.xml.bind.DatatypeConverter
Class
:
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);
}
但我得到以下 String
(
与 C# 相比缺少最后一个零 string
):
QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT09
在第二次尝试中,我使用了 BouncyCastle Base64
编码器:
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);
}
但我得到了与之前完全相同的 String
(
仍然缺少最后一个零):
QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT09
有人知道会发生什么吗?
我看过 .NET 框架代码。 UrlTokenEncode
实际上从 base64 字符串的末尾删除了任何额外的 =
填充符号,并将它们替换为填充符号的数量,因此 0
、1
或 2
。这就是导致字符串末尾出现额外 0
的原因。所以请注意:HttpServerUtility.UrlTokenEncode
方法不是普通的 Base64 编码器。它实际上在内部使用 Convert.ToBase64String
进行常规编码,并在顶部添加更多内容(请参阅我对问题的评论)。如果您需要创建这个确切的字符串,则需要在常规 base64 编码之上对 Java 进行相同的更改。
我根据大家给我的评论找到了解决方案,基本上我是看Reference Source of Microsoft.
中方法的源码
然后我将 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;
}
}
最后我测试了这个方法,我得到了想要的输出:
public static void main(String[] args) {
String strWord = "Bpz2Gjg01d7VfGfD8ZP1UA==";
byte[] encbuff = strWord.getBytes(StandardCharsets.UTF_8);
String strWordEncoded = UrlTokenEncode(encbuff);
}
M2NIclh4eEwxRGp2MEsyeFc0SHVDZz090
我在尝试对 Java 中的 String
进行编码时遇到了问题。
我在 C# 中有以下代码,当我执行 C# 代码时,string
Bpz2Gjg01d7VfGfD8ZP1UA==得到:
QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT090
public static void Main(string[] args)
{
string strWord = "Bpz2Gjg01d7VfGfD8ZP1UA==";
byte[] encbuff = Encoding.UTF8.GetBytes(strWord);
string strWordEncoded = HttpServerUtility.UrlTokenEncode(encbuff);
Console.WriteLine(strWordEncoded);
}
我试图在第一个中复制 Java 中的先前代码
尝试我使用 javax.xml.bind.DatatypeConverter
Class
:
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);
}
但我得到以下 String
(
与 C# 相比缺少最后一个零 string
):
QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT09
在第二次尝试中,我使用了 BouncyCastle Base64
编码器:
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);
}
但我得到了与之前完全相同的 String
(
仍然缺少最后一个零):
QnB6MkdqZzAxZDdWZkdmRDhaUDFVQT09
有人知道会发生什么吗?
我看过 .NET 框架代码。 UrlTokenEncode
实际上从 base64 字符串的末尾删除了任何额外的 =
填充符号,并将它们替换为填充符号的数量,因此 0
、1
或 2
。这就是导致字符串末尾出现额外 0
的原因。所以请注意:HttpServerUtility.UrlTokenEncode
方法不是普通的 Base64 编码器。它实际上在内部使用 Convert.ToBase64String
进行常规编码,并在顶部添加更多内容(请参阅我对问题的评论)。如果您需要创建这个确切的字符串,则需要在常规 base64 编码之上对 Java 进行相同的更改。
我根据大家给我的评论找到了解决方案,基本上我是看Reference Source of Microsoft.
中方法的源码然后我将 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;
}
}
最后我测试了这个方法,我得到了想要的输出:
public static void main(String[] args) {
String strWord = "Bpz2Gjg01d7VfGfD8ZP1UA==";
byte[] encbuff = strWord.getBytes(StandardCharsets.UTF_8);
String strWordEncoded = UrlTokenEncode(encbuff);
}
M2NIclh4eEwxRGp2MEsyeFc0SHVDZz090