【问题标题】:How efficient is the encoding/decoding algorithm of BASE64 class in Java?Java中BASE64类的编码/解码算法效率如何?
【发布时间】:2011-06-15 18:56:09
【问题描述】:

我将使用一种算法对从 XML 文件中检索到的可变长度但很长的 String 字段进行编码,然后将该编码数据保存在数据库中。

稍后,当我收到第二个文件时,我需要从数据库(之前存储的)中获取编码数据,然后对其进行解码并使用新数据进行验证以进行重复。

我试过org.apache.commons.codec.binary.Base64类 它有两种方法:

  1. encodeBase64(Byte[] barray)
  2. decodeBase64(String str)

效果很好,解决了我的问题。 但它将 55 个字符的字符串转换为 6 个字符的字符串。

所以我想知道这些算法是否会在任何情况下将 2 个非常大且只有 1 个字符不匹配(例如)的字符串编码到相同的编码字节数组中。

我不太了解Base64 课程,但如果有人可以帮助我,那将非常有帮助。

如果您可以建议任何其他算法,使大字符串短于固定长度并解决我的目的,我将很乐意使用它。

提前致谢。

【问题讨论】:

  • base64 的任何正确实现都会使字符串变大而不是变小。你想压缩字符串吗?
  • 是的,实际上我需要一些算法来将长字符串压缩成较小的字符串并存储在数据库中,然后对其进行膨胀以获得原始字符串。我在网上看到了ZipOutputStream类的实现,但没试过。
  • 我认为您正在寻找诸如 MD5 之类的哈希函数(它将所有输入转换为 128 字节的输出)。 Base64 编码通常会产生输入大小的三分之四的输出 - 所以它根本不会产生固定长度的输出。
  • 好的,我明白了。那么你建议用什么算法来解决我的问题?你能给我一个链接到任何例子吗
  • 您是否只是想确定输入字符串是否已存储在数据库中?如果是这样,选择适当的散列函数并存储散列值可能就足够了。不同的哈希函数具有不同的特性(性能、冲突的可能性等),您需要进行一些研究以选择适合您需求的一种。

标签: java encoding base64 apache-commons-codec string-decoding


【解决方案1】:

效率不高。

另外,使用sun.misc 类会产生一个不可移植的应用程序。

查看来自MiGBase64 的以下性能比较:


所以我想知道是否有任何情况 这些算法编码 2 个字符串 它们非常大,只有 1 个 字符不匹配(例如)到相同 编码字节数组。

Base64 不是散列算法,它是一种编码,因此必须是双向的。必须不允许碰撞 - 否则解码将是不确定的。 Base64 旨在表示 ASCII 字符串中的任意二进制数据。将 Unicode 字符串编码为 Base64 通常会增加所需的 代码点数,因为 Unicode 字符集需要多个字节。 Unicode 字符串的 Base64 表示将根据使用的编码(UTF-8、UTF-16)而有所不同。例如:

Base64( UTF8( "test" ) ) => "dGVzdA=="
Base64( UTF16( "test" ) ) => "/v8AdABlAHMAdA=="

解决方案 1

使用无损压缩

GZip( UTF8( "test" ) )

在这里,您将字符串转换为字节数组并使用无损压缩来减少您必须存储的字节数。您可以根据要存储的字符串改变 char 编码和压缩算法以减少字节数(即,如果它主要是 ASCII,那么 UTF-8 可能是最好的。

优点:没有冲突,能够恢复原始字符串
缺点:存储值所需的字节数是可变的;存储值所需的字节数更大

解决方案 2

使用散列算法

SHA256( UTF8( "test" ) )

在这里,您使用散列函数将字符串转换为固定长度的字节集。散列是单向的,本质上是collisions can be possible。但是,根据您希望处理的字符串的配置文件和数量,您可以选择一个哈希函数来最大限度地减少冲突的可能性

优点:存储值所需的字节数是固定的;存储值所需的字节数很小
缺点:可能发生冲突,无法恢复原始字符串

【讨论】:

  • @johnstok 你能告诉我一种有效压缩和解压缩字符串的方法吗?
  • @johnstok 我对答案很满意 ....accepted,尽管我使用 java.util.zip.Deflater 和 Inflater 类来有效地压缩/解压缩字符串。现在出现另一个问题,压缩后生成的输出字符串包含即使我尝试以 UTF8 格式压缩它,eclipse 控制台也无法显示的字符,我必须检查我的数据库是否支持压缩字符串输出。任何方式都非常感谢您的回答。
  • @Subhadip 使用 java.util.zip.Deflater 压缩将产生一个字节数组 - 而不是字符串。您可以将其存储在 SQL BLOB 或 BINARY 列中。
【解决方案2】:

我刚刚看到您的评论 - 看来您实际上是在寻找压缩而不是像我最初想的那样进行散列。虽然在那种情况下,您不会能够为任意输入获得固定长度的输出(想想看,无限数量的输入不能双射映射到有限数量的输出),所以我希望这不是一个强烈的要求。

无论如何,您选择的压缩算法的性能将取决于输入文本的特征。在没有更多信息的情况下,DEFLATE 压缩(Zip 输入流使用,IIRC)是一个很好的通用算法,至少可以用作比较的基础。不过,为了便于实施,您可以使用 JDK 中内置的 Deflator 类,该类使用 ZLib 压缩。

如果您的输入字符串具有特定的模式,那么不同的压缩算法可能或多或少有效率。在一方面,您使用哪一个并不重要,如果您不打算让任何其他进程读取压缩数据 - 只要您可以自己压缩和解压缩,它对您的客户是透明的。

这些其他问题可能很有趣:

【讨论】:

  • 首先感谢您的建议,我明白您所说的。Base64 在这里解决了我的目的,但我担心的是我是否可以相信 Base64 算法将有足够的能力进行编码并有效解码所有较大的字符串。是否存在 Base64 算法为仅相差一个字符左右的大字符串生成相同输出的情况?
  • base64 能解决您的问题吗?我以为你想让字符串更小 - base64 会导致 larger 输出。而且它也没有对输出大小设置任何上限——如果输入是 3000 个字符,编码后的输出将是 4000 个字符——所以这可能无法满足您对“对所有较大字符串进行有效编码”的要求。不过,在回答您的最后一个问题时,不会有任何冲突; base64 是完全双向的。
  • 是的,很抱歉,我最初认为 Base64 类会压缩输出。但后来发现 java.util.zip.Deflater 和 java.util.zip.Inflater 类是我需要的,但再次卡在压缩字符串的输出中,它不是 Unicode 格式。我尝试将其重新定义为 UTF8,但我的 Eclipse 控制台上显示的字符串文字虽然不是 UTF8 格式。我将不得不看看这些数据是否可以保存到我的 Oracle 数据库中。无论如何感谢您的帮助:) 干杯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-21
  • 1970-01-01
相关资源
最近更新 更多