6

我无法在 Java (Android) 和 .NET (Visual Basic) 中将文本转换为 Base64 字符串。ASCII 字符的普通(可读)形式可以很好地转换。但是当涉及到特殊字符(代码大于 128 的字符)时,它们给我带来了麻烦。

例如,我尝试转换 ASCII 值为 65 的字符代码(字符“A”)。

我的Java代码是:

char a = 65;
String c = String.valueOf(a); 
byte bt[] = c.getBytes();               
String result = Base64.encodeToString(bt, Base64.DEFAULT);

我的 .NET 代码是:

Dim c As String = Chr(65)
Dim result as String = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(c))

它们都返回相同的结果:“QQ==”。这可以。但是当我尝试转换一个特殊字符时,例如一个字符代码 153。然后它返回不同的结果。

char a = 153;
String c = String.valueOf(a);               
byte bt[] = c.getBytes();               
String result = Base64.encodeToString(bt, Base64.DEFAULT);

这将返回“wpk=”

和我相同的 .NET 代码:

Dim c As String = Chr(153) 
Dim result as String = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(c))

这将返回“4oSi”

这太奇怪了。这里有什么问题。我在两个平台上都使用本机 Base64 库。我的代码有问题吗?

4

1 回答 1

11

由于您正在编码的数据是加密数据 - 任何字节都可以从 0 到 255 的随机数据,并且在其加密状态下,没有字符或文本含义,因此您需要将此信息视为 - 让我们称之为 -true binary数据。Java 和 .NET 都通过各自的字节数组原语完全支持真正的二进制数据。

如您所知,base64 编码是将真正的二进制数据(范围为 0 到 255)转换为稍大的二进制数据数组(其中每个字节保证与 32 之间的 ASCII 可打印字符具有相同的值)的过程和 126)。让我们称之为encoded binary. 然后encoded binary可以安全地将其转换为文本,因为几乎每个已知字符集都同意可打印的 ASCII 字符集(32 到 126)。

因此,Java 和 VB.NET 片段的主要问题是您试图使用文本原语 - Java 中的 char 和 String;VB.NET 中用于存储true binary数据的字符串。一旦你这样做就太晚了。没有办法将其可靠地转换回字节数组,因为文本原语根本不是为了安全地存储和检索二进制数据而设计的。有关为什么会这样的更多信息,请阅读每个软件开发人员绝对、肯定必须了解 Unicode 和字符集的绝对最低要求(没有借口!)

幸运的是,修复很简单。对于 Java,不要使用 char 和 String 来存储二进制数据。将数据直接放入字节数组。尝试以下操作:

  byte [] bt = new byte[1];
  bt[0] = (byte) 153;
  String result = Base64.encodeToString(bt, Base64.DEFAULT);

我得到 mQ==

该修复在 VB.NET 中在概念上是相同的。不要使用字符串。使用字节数组。

    Dim bytes() As Byte = New Byte() {153}
    Dim result As String = Convert.ToBase64String(bytes)

再次 - 答案是 mQ==

最后,在编码之后,使用字符串就完全没问题了。您的字符在 ASCII 子集中,字符串和字节数组之间的任何转换都不会损坏数据,因为所有字符集都同意 ASCII 子集。

请记住,您将以相反的顺序遇到相同的问题 - 解码。您将解码为一个字节数组,此时您将返回true binary. 从这一点开始,数据绝不能存储为字符串 - 直到你完成它 - 例如。将其解密回原始明文。

希望这可以帮助。

于 2012-10-22T19:01:45.617 回答