写入转义字节字符的字符串,即'\ x00 \ x20 \ ...',就好像它们是字节一样

时间:2015-08-04 20:45:45

标签: python python-2.7

我正在使用.wav文件生成,并具有将基本10整数转换为十六进制的函数。我需要将这些十六进制数字写成字节,而不是简单地将它们编码为字节。我可以使用转义序列进行硬编码,但我需要使用我的函数提供的字符串。

我的临时工作如下所示使用eval。

eval("b'" + endian(bytestring(tohex(16, 32))) + "'")

在没有eval的情况下完成此任务的更优选方法是什么?

以下是一些可以更好地了解情况的代码。

with open('song.wav', 'wb') as f:
    f.write(ChunkID)
    f.write(ChunkSize)
    f.write(Format)
    f.write(Subchunk1ID)
    f.write(Subchunk1Size)
    f.write(AudioFormat)
    f.write(NumChannels)
    f.write(SampleRate)
    f.write(ByteRate)
    f.write(BlockAlign)
    f.write(BitsPerSample)
    f.write(Subchunk2ID)
    f.write(Subchunk2Size)
    f.write(Data)

使用硬编码值可以正常工作。

ChunkID = b'RIFF'               #big        1
ChunkSize = b'\x1a\xea\xc4\x00'     #little     2
Format = b'WAVE'                #big        3
Subchunk1ID = b'fmt '               #big        4
Subchunk1Size = b'\x10\x00\x00\x00'         #little     5
AudioFormat = b'\x01\x00'           #little     6
NumChannels = b'\x02\x00'           #little     7
SampleRate = b'\x22\x56\x00\x00'        #little     8
ByteRate = b'\x88\x58\x01\x00'          #little     9
BlockAlign = b'\x04\x00'            #little     10
BitsPerSample = b'\x10\x00'         #little     11
Subchunk2ID = b'data'               #big        12
Subchunk2Size = b'\x10\xb1\x02\x00'     #little     13
Data = b''                  #little     14

我需要更多的灵活性,并且需要使用函数来获得类似的结果。

def tohex(val, nbits):
    a = hex((val + (1 << nbits)) % (1 << nbits))
    pad = nbits/4 - (len(a) - 2)
    for i in range(0, pad):
        a = a[:2] + '0' + a[2:]
    return a
def bytestring(hexstring):
    hexstring = hexstring[2:]
    bstring = ''
    for i in range(0, len(hexstring)/2):
        bstring += '\\x'
        bstring += hexstring[2*i: 2*i+2]
    return bstring
def endian(bstring):
    return '\\'+'\\'.join(reversed(bstring.split('\\'))).rstrip('\\')

这就是我调用函数的方式

sample_rate = 44100
channels = 2
sample_bits = 16
sample_count = 176400

ChunkID = b'RIFF'
Format = b'WAVE'
Subchunk1ID = b'fmt '
Subchunk1Size = eval("b'" + endian(bytestring(tohex(16, 32))) + "'")    #n bit samples : tohex(n,m)
AudioFormat = eval("b'" + endian(bytestring(tohex(1, 16))) + "'")       #uncompressed when n=1
NumChannels = eval("b'" + endian(bytestring(tohex(channels, 16))) + "'")        #n channels
SampleRate = eval("b'" + endian(bytestring(tohex(sample_rate, 32))) + "'")
BitsPerSample = eval("b'" + endian(bytestring(tohex(sample_bits, 16))) + "'")
ByteRate = eval("b'" +  endian(bytestring(tohex(sample_rate*channels*sample_bits/8, 32))) + "'")
BlockAlign = eval("b'" + endian(bytestring(tohex(channels*sample_bits/8, 16))) + "'")
Subchunk2ID = b'data'
Subchunk2Size = eval("b'" + endian(bytestring(tohex(sample_count*channels*sample_bits/8, 32))) + "'")
ChunkSize = eval("b'" + endian(bytestring(tohex(36 + sample_count*channels*sample_bits/8, 32))) + "'")
Data = b''

for i in range(0, 176400): #Just test samples
    if i % 32 < 16:
        Data += b'\x10\xe7\x10\xe7'
    else:
        Data += b'\xf0\xa8\xf0\xa8'

更新:我添加了一个新函数来处理以前的格式并返回一个我可以直接写入文件的表单。我标记的解决方案使用字节但在python 2.7中我必须使用bytearray。

def barray(bstring):
    hexmap = {'0':0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7,'8':8, '9':9, 'a':10, 'b':11, 'c':12, 'd':13, 'e':14, 'f':15}
    bstring = bstring.lstrip('\\x')
    bstring = bstring.split('\\x')
    bstring = map(lambda x: 16*hexmap[x[0]]+hexmap[x[1]], bstring)
    return bytearray(bstring)

现在,在调用函数之后,数据就可以在不使用eval()的情况下写入文件。

variable = barray(endian(bytestring(tohex(n, m))))

1 个答案:

答案 0 :(得分:1)

您是否尝试使用bytes

data = '\x00\x20\x10'
newdata = [int(i) for i in data.encode()]
print(newdata)
>>> [0, 32, 16]
print(bytes(newdata))
>>> b'\x00 \x10'  # it only looks like the middle value is missing, it isn't
print([i for i in b'\x00 \x10'])
>>> [0, 32, 16]  # yep, all still there

根据澄清之后对问题的更好理解进行编辑。