文件中的unicode字符串包含不同的

时间:2012-04-14 13:30:59

标签: python sqlite unicode utf-16

我的系统是fedora。出于某种原因。一条记录的最后一个字段是一个unicode字符串(使用来自qemu中来宾计算机的memcpy复制数据)。 unicode字符串是windows regedit键名。

  

SMSS.EXE | NtOpenKey | 304 | 4 | 4 | 0 | \ ^ 5 R ^ | E ^ @ G ^ @ I ^ @小号^ @ T ^ 2 R ^ @ Y 1 @ \ ^ @ M 1 @一个^ @ C 1-4 @ H ^ @ I ^ @ N ^ | E ^ @ \ ^ @小号^ @ Y 1 @小号^ @ T ^ | E ^ @立方公尺@ \ ^ @ C 1-4 @ú^ 2 R ^ @ R 2 | E ^ @ N ^ @ T ^ @ C 1-4 @ o ^ @ N ^ @ T ^ 2 R ^ @ o ^ @ L ^ @小号^ | E ^ @ T ^ @ \ ^ @ C 1-4 @Ò ^ @ n ^ @ t ^ @ r ^ @ o ^ @ l ^ @ \ ^ @ S ^ @ e ^ @ s ^ @ s ^ @ i ^ @ o ^ @ n ^ @ ^ @ M ^ @ a ^ @ n ^ @一个^ @ G ^ | E ^ @ R 1 @   SMSS.EXE | NtClose | 304 | 4 | 4 | 0 |系统| NtOpenKey | 4 | 0 | 2147484532 | 0 | \ ^ 5 R ^ | E ^ @ G ^ @ I ^ @小号^ @ T ^ @ R 1 @ Y 1 @ \ ^ @ M 1 @一个^ @ C 1-4 @ H ^ @ I ^ @ N ^ | E ^ @ \ ^ @小号^ @ Y 1 @小号^ @ T ^ | E ^ @立方公尺@ \ ^ @ C 1-4 @ú^ @ R 1 @ R 2 | E ^ @ N ^ @ T ^ @ C 1-4 @ o ^ @ N ^ @ T ^ 2 R ^ @ o ^ @ L ^ @小号^ | E ^ @吨^ @   Services.exe的| NtOpenKey | 680 | 624 | 636 | 0 | \ ^ 5 R ^ | E ^ @ G ^ @ I ^ @小号^ @ T ^ 2 R ^ @ Y 1 @ \ ^ @ M 1 @甲^ @ C 1-4 @ H ^ @ I ^ @ N ^ | E ^ @ \ ^ @小号^ @ Y 1 @小号^ @ T ^ | E ^ @立方公尺@ \ ^ @ C 1-4 @ú^ @ R 1 @ R 1 | E ^ @ N ^ @ T ^ @ C 1-4 @ o ^ @ N ^ @ T ^ 2 R ^ @ o ^ @ L ^ @小号^ | E ^ @ T ^ @ \ ^ @小号^ | E ^ 5 R ^ @ v ^ @ I ^ @ C 1-6 | E ^ @小号^ @

以下是一些十六进制代码:使用'|'作为分裂字符。前6个字段是ascii sting。最后一个字段是一个窗口unicode字符串(我认为它是utf-16代码)。

  

0000000 6d73 7373 652e 6578 4e7c 4f74 6570 4b6e
  0000010 7965 337c 3430 347c 347c 307c 5c7c 5200
  0000020 6500 6700 6900 7300 7400 7200 7900 5c00
  0000030 4d00 6100 6300 6800 6900 6e00 6500 5c00
  0000040 5300 7900 7300 7400 6500 6d00 5c00 4300
  0000050 7500 7200 7200 6500 6e00 7400 4300 6f00
  0000060 6e00 7400 7200 6f00 6c00 5300 6500 7400
  0000070 5c00 4300 6f00 6e00 7400 7200 6f00 6c00
  0000080 5c00 5300 6500 7300 7300 6900 6f00 6e00
  0000090 2000 4d00 6100 6e00 6100 6700 6500 7200

我将使用python来解析它并将其插入数据库。这是我如何处理

def parsecreate(filename):
    sourcefile = codecs.open("data.db",mode="r",encoding='utf-8')
    cx = sqlite3.connect("sqlite.db")
    cu = cx.cursor()
    cu.execute("create table data(id integer primary key,command text, ntfunc text, pid text, ppid text, handle text, roothandle text, genevalue text)")
    eachline = []
    for lines in sourcefile:
        eachline = lines.split('|')
        eachline[-1] = eachline[-1].strip('\n')
        eachline[-1] = eachline[-1].decode('utf-8')

        cu.execute("insert into data(command,ntfunc,pid,ppid,handle,roothandle,genevalue) values(?,?,?,?,?,?,?)",(eachline[0],eachline[1],eachline[2],eachline[3],eachline[4],eachline[5],eachline[-1]) )

    cx.commit()
    cx.close()

我错了:

  

文件“./parse1.py”,第18行,在parsecreate中      对于源文件中的行:    文件“/usr/lib/python2.7/codecs.py”,第684行,下一步      return self.reader.next()    文件“/usr/lib/python2.7/codecs.py”,第615行,下一步      line = self.readline()    在readline中文件“/usr/lib/python2.7/codecs.py”,第530行      data = self.read(readsize,firstline = True)    文件“/usr/lib/python2.7/codecs.py”,第477行,读入      newchars,decodingbytes = self.decode(data,self.errors)   UnicodeDecodeError:'utf8'编解码器无法解码位置51的字节 0xd0 :无效的连续字节

因为unicode字符串可能包含utf8不知道的字节。  如何才能正确阅读最后一个字段?

简单地说。在utf-16编码文件中有一个unicode字符串,如何才能正确地将字段插入到db中? Python使用一种编码样式读取文件。我可以只读取原始字节。可以将这些字节组合成一个unicode字符串。

1 个答案:

答案 0 :(得分:3)

您的数据文件不是纯文本文件,因此请将文件作为二进制文件打开,并明确解码文本字段。我不得不操纵数据以回到我认为的原始二进制数据。看起来原始数据可能是sqlite3.exe转储类似于下面的最终输出,除了最终字段的数据存储为UTF-16编码的BLOB而不是TEXT。

请注意,按行解析并按“|”拆分如果UTF-16数据包含代表'\ n'或'|'的字节,可能会遇到问题,但我暂时忽略它。

这是我的测试:

from binascii import unhexlify
import sqlite3

data = unhexlify('''\
6d73 7373 652e 6578 4e7c 4f74 6570 4b6e
7965 337c 3430 347c 347c 307c 5c7c 5200
6500 6700 6900 7300 7400 7200 7900 5c00
4d00 6100 6300 6800 6900 6e00 6500 5c00
5300 7900 7300 7400 6500 6d00 5c00 4300
7500 7200 7200 6500 6e00 7400 4300 6f00
6e00 7400 7200 6f00 6c00 5300 6500 7400
5c00 4300 6f00 6e00 7400 7200 6f00 6c00
5c00 5300 6500 7300 7300 6900 6f00 6e00
2000 4d00 6100 6e00 6100 6700 6500 7200'''.replace(' ','').replace('\n',''))

# OP's data dump must have been decoded from the original data
# as little-endian words, and is missing a final 0x00 byte.
# Byte-swapping and adding missing zero byte to get back what
# was likely the original binary data.
data = ''.join(a+b for a,b in zip(data[1::2],data[::2])) + '\x00'

with open('data.db','wb') as f:
    f.write(data)

def parsecreate(filename):
    with open(filename,'rb') as sourcefile:
        with sqlite3.connect("sqlite.db") as cx:
            cu = cx.cursor()
            cu.execute("create table data(id integer primary key,command text, ntfunc text, pid text, ppid text, handle text, roothandle text, genevalue text)")
            eachline = []
            for line in sourcefile:
                eachline = line.split('|')
                eachline[-1] = eachline[-1].decode('utf-16le')
                cu.execute("insert into data(command,ntfunc,pid,ppid,handle,roothandle,genevalue) values(?,?,?,?,?,?,?)",(eachline[0],eachline[1],eachline[2],eachline[3],eachline[4],eachline[5],eachline[-1]) )

parsecreate('data.db')

输出:

C:\>sqlite3 sqlite.db
SQLite version 3.7.9 2011-11-01 00:52:41
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from data;
1|smss.exe|NtOpenKey|304|4|4|0|\Registry\Machine\System\CurrentControlSet\Control\Session Manager