Python:在二进制文件(.PLM)中搜索unicode字符串

2024-05-20 01:52:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图在windows10上使用python2.7从.PLM文件中提取一个目录名。PLM文件是松下录音机使用的专有文件格式,它存储录音目录的名称。你知道吗

(例如:假设我有一段录音,我想保存在“HelloÆØÅ”文件夹中,那么这个录音机会创建一个名为“SVÆVC001”的文件夹和一个名为“SD”的文件_语音.PLM在一堆其他数据中,存储字符串“HelloÆØÅ”)

现在,我是丹麦人,所以使用字符Æ,Ø和Å,这是ascii不支持的,所以我必须将这个二进制数据转换成unicode。你知道吗

到目前为止,我知道目录名是从字节56开始存储的,并以一个全0的字节结束。例如,一个记录存储在名为“2-3-15Årstids kredsløbet michael”的目录中,该目录具有十六进制值:

322d 332d 3135 20c5 7274 6964 7320 6b72 
6564 736c f862 6574 206d 6963 6861 656c

这是我目前使用的代码:

# Finds the filename in the .PLM-file
def  FindFileName(File):
    # Opens the file and points to byte 56, where the file name starts
    f = open(File,'rb')
    f.seek(56)
    Name = ""


    byte = f.read(1)        # Reads the first byte after byte 56
    while byte != "\x00":   # Runs the loop, until a NUL-character is found (00 is NUL in hex)
        Name += str(byte)   # Appends the current byte to the string Name
        byte = f.read(1)    # reads the next byte

    f.close()

    return Name

如果目录名只使用ASCII字符(因此没有“æ”、“ø”或“å”)的话,这种方法是有效的。你知道吗

但是,如果字符串中有unicode字符,则会将其转换为其他字符。在目录“2-3-15Årstids kredsløbet michael”下,该程序输出“2-3-15┼rtids kredsl°bet michael”

你有什么建议吗?
事先非常感谢。你知道吗

编辑

添加来自markransem的建议,代码如下。我还笨拙地处理了发现的3种边缘情况:问号改为空格,而\xc5和\xd8(分别用十六进制表示Ø和Ø)分别改为å和ø。你知道吗

def  FindFileName(File):
    # Opens the file and points to byte 56, where the file name starts
    f = open(File,'rb')
    f.seek(56)
    Name = ""


    byte = f.read(1)        # Reads the first byte after byte 56
    while byte and (byte != "\x00"):    # Runs the loop, until a NUL-character is found (00 is NUL in hex)

        # Since there are problems with "?" in directory names, we change those to spaces
        if byte == "?": 
            Name += " "
        elif byte == "\xc5":
            Name += "å"
        elif byte == "\xd8":
            Name += "ø"
        else:
            Name += byte

    byte = f.read(1)    # reads the next byte

f.close()

return Name.decode('mbcs')

对大写字母Æ、Ø和Å产生以下错误:

WindowsError: [Error 123] The filename, directory name, or volume label syntax is incorrect: u'C:\\Users\\UserName\\Desktop\\TestDir\\Mapper\\13-10*14 ESSOTERISK \xc5NDSSTR\xd8MNIN'

字符串应该是“13-10*14 ESSOTERISKÅNDSSTRØMNIN”,但Ø和Ø(十六进制c5和d8)是抛出错误。你知道吗


Tags: 文件thetonamein目录readis
1条回答
网友
1楼 · 发布于 2024-05-20 01:52:02

在python2中,从二进制文件读取将返回一个字符串,因此无需对其使用str。另外,如果由于某种原因文件格式不正确,并且其中没有零字节,read将返回一个空字符串。您可以通过对测试进行一个小的修改来检查这两种情况。你知道吗

while byte and (byte != "\x00"):   # Runs the loop, until a NUL-character is found (00 is NUL in hex)
    Name += byte        # Appends the current byte to the string Name
    byte = f.read(1)    # reads the next byte

一旦获得完整的字节序列,就必须将其转换为Unicode字符串。为此,您需要解码:

Name = Name.decode("utf-8")

正如在注释中提到的,看起来您的字符串实际上并不是UTF-8,而是微软的一个代码页。您可以从Windows当前使用的代码页进行解码:

Name = Name.decode("mbcs")

您可以显式地指定要使用的代码页,请参见the documentation。你知道吗

尝试在控制台上打印字符串时可能会遇到问题,因为Windows控制台与系统的其余部分不使用相同的代码页;它可能没有需要打印的字符。你知道吗

相关问题 更多 >