之前一直以为 Base64 很简单,真到自己去实现才发现没那么好写☹️。
require 'base64'
class String
def my_base64_encode(alphabeta = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
# 把 str 拆成字符组成的数组
str = self
ary = str.split('')
# 变成 2 进制
bin = ary.map { |e| "%08d" % e.ord.to_s(2) }
.reduce("") { |memo, e| memo += e }
# 分组:
bin.split('').each_slice(6).to_a
len = bin.split('').size
# puts "length: #{len} = #{len / 6} * 6 + #{len % 6}"
# puts "append: #{(6 - len % 6) % 6} bits zero. "
# 填充:
bin += ( '0' * ((6 - len % 6) % 6) )
bin.split('').each_slice(6).to_a
bs = bin.split('').each_slice(6).map { |e| alphabeta[e.join().to_i(2)] }
result = bs.reduce("") { |memo, e| memo += e }
# 填充 = :
result += ( '=' * ((6 - len % 6) % 6 / 2) )
end
def my_base64_decode(alphabeta = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
# 把 str 拆成字符组成的数组
str = self.chomp
dictionary = {}
alphabeta.split('').each_with_index { |e, i| dictionary[e] = i }
tail = str.scan(/=+$/).first || ""
count = tail.size
ary = str.gsub(/=+$/, '').split('')
# pp ary.map { |e| dictionary[e] }
bin = ary.map { |e| "%06d" % dictionary[e].to_s(2) }
s = bin.join
result = s[0...(s.size - count * 2)]
.split('')
.each_slice(8)
.to_a
.map { |e| e.join.to_i(2).chr }
.join
end
end
str = "sky"
puts str.my_base64_encode #=> c2t5
puts Base64.encode64(str) #=> c2t5
puts Base64.encode64(str).my_base64_decode #=> sky
str = "ABCD"
puts str.my_base64_encode #=> QUJDRA==
puts Base64.encode64(str) #=> QUJDRA==
puts Base64.encode64(str).my_base64_decode #=> ABCD
str = "command?"
puts str.my_base64_encode("aABCDEFGHIJKLMNOPQRSTUVWXYZbcdefghijklmnopqrstuvwxyz0123456789+/") #=> X29tbVEuYC8=
puts Base64.encode64(str) #=> Y29tbWFuZD8=
puts str.my_base64_encode("aABCDEFGHIJKLMNOPQRSTUVWXYZbcdefghijklmnopqrstuvwxyz0123456789+/")
.my_base64_decode("aABCDEFGHIJKLMNOPQRSTUVWXYZbcdefghijklmnopqrstuvwxyz0123456789+/") #=> command?
网友评论