我试图用python解码ID3v2(MP3头)协议。要解码的数据格式如下。在
s1
,s2
。。。sn-1
是unicode(utf-16/utf-8)字符串,最后一个字符串“sn”可以是unicode或二进制字符串。在
data = s1+delimiters+s2+delimiters+...+sn
其中,utf-16的分隔符是'\x00'+'\x00'
utf-8的分隔符是'\x00'
我得到data
和unicode类型。现在我必须提取所有字符串(s1
,s2
。。。sn
)来自data
。为此,我使用split()
,如下所示
输出:
['Hello', 'world']
['\xff\xfeH\x00e\x00l\x00l\x00o', '\x00\xff\xfew\x00o\x00r\x00l\x00d\x00']
它适用于set-1数据,但不适用于set-2。 因为“数据”在集合2中
'\xff\xfeH\x00e\x00l\x00l\x00o\x00\x00\x00\xff\xfew\x00o\x00r\x00l\x00d\x00'
^ ^
在分隔符前面有一个额外的'\x00'
,由于字母“0”,它无法正常工作。在
有谁能帮我正确解码这两种情况的“数据”吗?在
更新:
我会尽量把问题简单化。 s1=编码(utf-8/utf-16)字符串
s2=二进制字符串(非unicode)
utf-16的分隔符是'\x00'+'\x00'
,utf-8的分隔符是'\x00'
数据=(s1+分隔符)+s2
有人能帮我从“数据”中提取s1和s2吗?在
更新2:解决方案
下面的代码符合我的要求
def splitNullTerminatedEncStrings(self, data, encoding_type, no_of_splits):
data_dec = data.decode(encoding_type, 'ignore')
chunks = data_dec.split('\x00', no_of_splits)
enc_str_lst = []
for data_dec_seg in chunks[:-1]:
enc_str_lst.append(data_dec_seg.encode(encoding_type))
data_dec_chunks = '\x00'.join(chunks[:-1])
if(data_dec_chunks): data_dec_chunks += '\x00'
data_chunks = data_dec_chunks.encode(encoding_type)
data_chunks_len = len(data_chunks)
enc_str_lst.append(data[data_chunks_len:]) # last segment
return enc_str_lst
你为什么不先解码这些字符串呢?在
Python 2:
Python 3:
^{pr2}$然后直接对不可知的数据进行编码,定界符总是一个空值。在
不完全是。UTF-16的分隔符是
\0\0
,仅在代码单元边界处。一个代码单元末尾的\0
后跟另一个代码单元开头的\0
不构成分隔符。ID3标准讨论字节“同步”意味着情况并非如此,但它是错误的。在[旁白:不幸的是,许多标签读取工具确实是这样理解的,结果是任何带有双零字节的序列(例如UTF-16BE中的U+0100、U+0061
Āa
,或者,正如您所发现的,UTF-16LE中字符串末尾的任何ASCII)都会破坏帧。因此,UTF-16文本格式(UTF-16+BOM 0x01和UTF-16BE 0x02)完全不可靠,所有标记编写器都应避免使用。文本格式0x00对于任何东西都是不可靠的,除了纯ASCII。UTF-8是冠军!]在如果您有一个编码结束字符串结构的列表,类似于为
T
帧(而不是TXXX
)指定的结构,那么简单的方法是在U+0000终止符上拆分它们之前对它们进行解码:如果
data
是一个完整的ID3帧,恐怕不能用单个的split()
来处理它。除T
系列以外的帧包含以编码结束的字符串、仅以ASCII结尾的字符串、二进制对象(没有终止)和整数字节/字值。APIC
就是这样一个例子,但是对于一般情况,您必须事先知道要解析的每个帧的结构,并逐个使用每个字段,在执行过程中手动查找每个终止符。在要在UTF-16编码的数据中找到与代码单元对齐的终止符而不误解
^{pr2}$Āa
等,可以使用regex,例如:这真的不是很有趣-ID3v2不是一个非常干净的格式。在我的头脑中,这是一种未经考验的方法:
下面的代码符合我的要求
相关问题 更多 >
编程相关推荐