【问题标题】:How do I encode hexadecimal to base64 in python?如何在python中将十六进制编码为base64?
【发布时间】:2019-02-24 18:49:28
【问题描述】:

如果我尝试这样做:

from base64 import b64encode
b64encode('ffffff')

我收到此错误:

Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    base64.b64encode('ffffff')
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/base64.py", line 58, in b64encode
    encoded = binascii.b2a_base64(s, newline=False)
TypeError: a bytes-like object is required, not 'str'

因为它说的是类似字节的对象,所以我尝试了这个:

b64encode(bytes('ffffff'))

失败了。

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    b64encode(bytes('ffffff'))
TypeError: string argument without an encoding

最后,使用.encode('utf-8')函数:

b64encode('ffffff'.encode('utf-8'))

输出不正确b'ZmZmZmZm',正确的base64编码是////

我已经知道如何将 b64 解码为十六进制,所以不要说如何做到这一点。

编辑:这个问题被标记为与将十六进制字符串转换为十六进制字节相同。这涉及到base64。

【问题讨论】:

标签: python base64


【解决方案1】:

要从字符串ffffff 完全转换为十六进制值的base64,您需要使用codecs 模块对其进行一些编码和解码:

import codecs
# Convert string to hex
hex = codecs.decode('ffffff', 'hex')
# Encode as base64 (bytes)
codecs.encode(hex, 'base64')

对于像0xfffff这样的奇数字符串,你需要在十六进制字符串(0x0fffff)的开头放一个零,否则python会给你一个错误。

【讨论】:

  • 也可以通过struct.pack('B', int('ff',16))
  • 是的 - 虽然如果你为 base64 引入 codecs,我觉得将它用于这两个部分似乎更“整洁”。
  • 完全同意,手动解决这个问题并没有什么花哨的。但希望它能够教会人们编解码器为什么以及如何工作。所以我对十六进制的工作原理做了一个小小的解释。
  • @EricJin,您可以使用模数附加以获得正确的长度。 s = s + '0'*(len(s)%2)。如果字符串的长度不等于整数,则只会附加0。但是,这会给您带来不准确的结果,因为您可能不知道是否需要在字符串的开头或结尾附加 0?我的解决方案也适用于奇数长度。然而,它只是忽略了不完整的奇数。所以要小心。
【解决方案2】:

这是使用编解码器的替代方法。
这个可读性差一些,但效果很好,希望能教你编解码器、十六进制和整数是如何工作的。 (注意,在奇数长度上工作,但会忽略奇数字节字符串表示)

import struct
s = 'ffffff'
b''.join([struct.pack('B', int(''.join(x), 16)) for x in zip(s[0::2], s[1::2])])

应该给你b'\xff\xff\xff'

您的主要问题可能是您认为'ffffff' 代表值255, 255, 255。他们没有。它们仍然是带有字母 ff 的字符串格式。随后,您需要将十六进制的字符串表示解析/转换为实际的十六进制。我们可以通过首先将字符串传递给int() 来做到这一点,它可以以字符串表示格式使用十六进制。

您需要通过 int('ff', 16) 单独转换每对 ff,这会告诉 Python 将字符串转换为 base-16 整数(十六进制数字)。

然后将该整数转换为表示该整数的字节之类的对象。这就是struct.pack 的用武之地。它就是为此而生的。

struct.pack('B', 255) # 255 is given to us by int('ff', 16)

本质上,'B' 告诉 Python 将值 255 打包到一个 1 字节对象中,在这种情况下,这给了我们b'\xff',这是您的最终目标。现在,对原始数据中的每 2 对字母执行此操作。


这更像是一种手动方法,您将一次迭代字符串中的 2 个以上字符,并使用上述描述将它们捆绑成您期望的样子。或者只使用编解码器,无论哪种方式都可以。

上述oneliner的扩展版:

import struct
hex_string = 'ffffff'
result = b''
for pair in zip(hex_string[0::2], hex_string[1::2]):
    value = int(''.join(pair), 16)
    result += struct.pack('B', value)

至少,我希望这能解释十六进制在实际层面上的工作原理。以及计算机如何与人类可读的比特和字节版本相互渗透。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-10
    • 2012-01-23
    • 2018-09-10
    • 1970-01-01
    • 2017-12-05
    • 1970-01-01
    • 2016-04-17
    • 2020-06-15
    相关资源
    最近更新 更多