开发者社区 问答 正文

在python中如何从二进制文件中读取信息:报错

有一个二进制文件,文件中有n条记录,每条记录的格式是:

4个字节int + 长度为18的utf-8字符串 

用python读取int没有问题,但是在读取utf-8字符串时出现问题,因为utf-8占用的字节数是不定的,例如:‘abc’占用三个字节,而‘中国字’占用了6个字节。

该怎么读呢?尝试用codecs但是不成功

展开
收起
kun坤 2020-06-06 23:02:52 641 分享 版权
1 条回答
写回答
取消 提交回答
  • utf-8可以根据字的第一个字节移位推出长度的

    0xxxxxxx

    110xxxxx 10xxxxxx

    1110xxxx 10xxxxxx 10xxxxxx

    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx


    ######

    打开二进制文件用open('filename', 'rb')

    解码用s_unicode =  s.decode('UTF-8')



    ######

    谢谢楼上的回答。

    首先读取一个4字节的整形,然后再读取一个长度为18的utf-8字符串;这个长度为18的utf-8字符串的字节长度是不定的。

    所以您的方案似乎不行,或者我没有完全理解您的方案

    ######

    引用来自“甄码农”的答案

    谢谢楼上的回答。

    首先读取一个4字节的整形,然后再读取一个长度为18的utf-8字符串;这个长度为18的utf-8字符串的字节长度是不定的。

    所以您的方案似乎不行,或者我没有完全理解您的方案

    直接把4字节后的字符串decode出来就是中文了
    ######

    谢谢楼上的,根据你的提示,我搞定了,同时参考了这儿 http://zh.wikipedia.org/zh-cn/UTF-8

    下面是正确答案,给后来人用吧

    # -*- coding: utf-8 -*-
    
    def how_many_byte(a):
        """
            判断这个字符是由几个字节组成的        
            向右移2位,如果移位后的数字的各位都是1那么这个字符由6个字节组成
            向右移3位,如果移位后的数字的各位都是1那么这个字符由5个字节组成
            以此类推
        """
        bits = 8
        move_bits = 2
        while move_bits < bits:
            temp = (a >> move_bits)
            all_1 = 0
            for i in range(bits-move_bits):
                all_1 += 2**i
            if temp == all_1: return bits - move_bits
            move_bits += 1        
        return 1
    
        
    with open('t.txt','rb') as file_t:
        #读取3个字节跳过BOM
        file_t.read(3)
        while True:
            #读取一个字节
            a = file_t.read(1)
            if not a:
                print 'read to end of the file'
                break
            else:        
                bytes_count = how_many_byte(ord(a))
                print bytes_count
                if bytes_count > 1:
                    aleft = file_t.read(bytes_count-1)
                    a = a+aleft
                print '%s length is %i'%(a,len(a))

    ######

    引用来自“yisen”的答案

    引用来自“甄码农”的答案

    谢谢楼上的回答。

    首先读取一个4字节的整形,然后再读取一个长度为18的utf-8字符串;这个长度为18的utf-8字符串的字节长度是不定的。

    所以您的方案似乎不行,或者我没有完全理解您的方案

    直接把4字节后的字符串decode出来就是中文了

    关键是记录一条一条的不知道到哪儿结束,关键的问题是不知道下一个utf-8字符应该是几个字节的,搞定这个,问题也就解决了。

    谢谢您的热心帮助。

    ######

    在python的google group邮件组中发现了更好的办法,请看下面代码:

    # -*- coding: cp936 -*-
    import mmap
    import struct
    import StringIO
    import codecs
    
    
    decoder = codecs.getdecoder("utf-8")
    print dir(decoder)
     
    
    def read_int(stream):
        result = struct.unpack("l", stream.read(4))
        #print type(result)
        return result[0]
    
    def read_chars(reader,count):
        s = reader.read(chars=count, size=1)
        return s
        
    def read_stocks_from_file():
        datafile = r'D:\app\HKTest\HKServer\Data\stock.dat'
        with codecs.open(datafile, "r", "utf8", "ignore") as f:
            stream = f.stream
            count = read_int(stream)
            print '%i stocks' % count
            pos = f.tell()
            for index in xrange(count):
                market = read_int(stream)
                quote_type = read_int(stream)        
                code = read_chars(f.reader,6)
                stockname = read_chars(f.reader,16)
                pinyin =  read_chars(f.reader,8)
                lotsize = read_int(stream)
                underlying = read_int(stream)
                exdate = read_int(stream)
                stock = 'market:%s,type:%s,code:%s,stockname:%s,pinyin:%s,lotsize:%s' % (market,quote_type,code,stockname,pinyin,lotsize)        
                #if index % 100 == 0 :
                print stock
                #file_to_write.write(stock)
                #if index > 10 :break

    2020-06-06 23:02:58
    赞同 展开评论