在Ruby中的base64编码字符串中出现了奇怪的\n符号

191

Ruby中内置的Base64库会添加一些'\n'字符。我无法找出原因。对于这个特殊的例子:

irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'base64'
=> true
irb(main):003:0> str =  "1110--ad6ca0b06e1fbeb7e6518a0418a73a6e04a67054"
=> "1110--ad6ca0b06e1fbeb7e6518a0418a73a6e04a67054"
irb(main):004:0> Base64.encode64(str)
=> "MTExMC0tYWQ2Y2EwYjA2ZTFmYmViN2U2NTE4YTA0MThhNzNhNmUwNGE2NzA1\nNA==\n"

换行符"\n"位于字符串末尾的第6个位置。解码器(Base64.decode64)能够完美地还原原来的字符串。奇怪的是,这些换行符对编码后的字符串没有任何价值。当我从输出字符串中删除换行符时,解码器可以再次完美地解码。

irb(main):005:0> Base64.decode64(Base64.encode64(str).gsub("\n", '')) == str
=> true

我用另一个JS库生成了相同输入字符串的base64编码输出,输出没有换行符。

这是一个bug还是其他原因?有人遇到过这个问题吗?

顺便提一下,

$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]

同样的奇怪问题在这里。 - Nathan B
6个回答

282

编辑: 自从我写下这个答案之后,已经添加了Base64.strict_encode64(),它不会添加换行符。


文档有点混乱,b64encode方法应该为每60个字符添加一个换行符,而encode64方法的示例实际上是使用了b64encode方法。

似乎encode64使用的Array类的pack("m")方法也会添加换行符。考虑到这一点还不可选,我认为这是设计上的缺陷。

你可以自己删除换行符,或者如果你在使用rails,则可以使用ActiveSupport::CoreExtensions::Base64::Encoding中的encode64s方法。


49
自从我写下这个答案以来,似乎现在有了strict_encode64(),据说它不会添加换行符。 - Christoffer Hammarström
22
太蠢了!为什么你要这样对我,Ruby? - Josh M.
2
这是一个默认的assinie,但正如@ChristofferHammarström所提到的,现在有一种获取真正b64编码的方法。 - Dan
1
显然,这是为了保持与无法处理长行的软件的向后兼容性而存在的。https://dev59.com/wWIj5IYBdhLWcg3wuXWN#20065991 - Elliott Beach

122
在ruby-1.9.2中,你可以使用Base64.strict_encode64方法来进行编码,它不会在结尾添加\n(换行符)。

那是一个更简单的解决方案! - Avishai
我已经检查了Base64.strict_encode64,它没有正确编码三个字符的字符串。例如Base64.strict_encode64('abc') -> YWJj。 上述示例未正确编码。 - VijayGupta
@CodeMaker 我认为 YWJj 是正确的。有什么问题吗? - lulalala

13

使用strict_encode64方法。 encode64会在每60个字符处添加 \n。


1
我们可以将其更改为在76个符号后添加吗? - sonic

9

没错,这很正常。 文档 给出了一个演示行拆分的示例。其他语言中也有base64执行相同的操作(例如Python)。

在编码阶段添加无内容换行符的原因是,base64最初是作为在电子邮件中发送二进制内容的编码机制而设计的,在那里行长受限。如果不需要它们,请随意将其替换掉。


1
这是我在我的Android应用程序(Java的Base64库)中遇到的问题。我完全被这个奇怪的错误搞糊涂了。花了我整整一个小时才找出问题所在,然后搜索错误信息。即使过去6年了,这个评论仍有助于理解遗留问题。 - burglarhobbit

6
似乎它们需要被剥离/忽略,例如:
Base64.encode64(str).gsub(/\n/, '')

这个解决方案很糟糕..还有其他的吗? - Arnold Roa
1
@yaauie(通过建议的编辑):通常不应进行对内容做出实质性更改的编辑。我建议将其作为单独的答案发布。 - Pokechu22

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接