[英]Write string of escaped byte characters, ie '\x00\x20\…', as if they were bytes
我正在玩.wav文件生成,並具有將基數10的整數轉換為十六進制的函數。 我需要將這些十六進制數字寫為字節,而不是簡單地將它們編碼為字節。 我可以使用轉義序列進行硬編碼,但是我需要使用函數提供的字符串。
我的臨時工作如下使用eval。
eval("b'" + endian(bytestring(tohex(16, 32))) + "'")
在沒有評估的情況下完成此任務的更優選方法是什么?
這里有一些代碼可以更好地了解情況。
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))))
您嘗試使用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
在澄清問題后,根據對問題的更好理解進行編輯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.