我的任务是读取格式不正确的二进制文件并接收变量。虽然我需要用 C++(特别是 ROOT)来做,但我决定用 Python 来做,因为 Python 对我来说很有意义,但我的计划是先让它在 Python 中工作,然后再用 C++ 重写,所以使用易于使用的 python 模块不会让我在以后的道路上走得太远。
基本上,我这样做:
In [5]: some_value
Out[5]: '\x00I'
In [6]: ''.join([str(ord(i)) for i in some_value])
Out[6]: '073'
In [7]: int(''.join([str(ord(i)) for i in some_value]))
Out[7]: 73
而且我知道必须有更好的方法。你怎么看?
编辑:
关于二进制格式的一些信息。
alt text http://grab.by/3njm alt text http://grab.by/3njv alt text http://grab.by/3nkL
这是我正在使用的字节序测试:
# Read a uint32 for endianess
endian_test = rq1_file.read(uint32)
if endian_test == '\x04\x03\x02\x01':
print "Endian test: \\x04\\x03\\x02\\x01"
swapbits = True
elif endian_test == '\x01\x02\x03\x04':
print "Endian test: \\x01\\x02\\x03\\x04"
swapbits = False
请您参考如下方法:
您的 int(''.join([str(ord(i)) for i in some_value])) 只有在除最后一个字节以外的所有字节都为零时才有效。 例子:
'\x01I' 应该是 1 * 256 + 73 == 329;你得到 173
'\x01\x02' 应该是 1 * 256 + 2 == 258;你得到 12
'\x01\x00' 应该是 1 * 256 + 0 == 256;你得到 10
它还依赖于整数存储在 bigendian 中的假设时尚;你验证过这个假设吗?您确定 '\x00I' 代表整数 73,而不是整数 73 * 256 + 0 == 18688(或其他)吗?请让我们通过告诉我们什么品牌和型号的计算机以及使用什么操作系统来创建数据来帮助您验证这个假设。
如何表示负整数?
您需要处理 float 吗?
用C++写的要求是不可变的吗? “(特别是 ROOT)”是什么意思?
如果唯一的命令是常识,首选顺序是:
使用 struct 模块用 Python 编写它。
用 C++ 编写,但使用 C++ 库例程(尤其是涉及 float 时)。不要重新发明轮子。
使用 C++ 编写您自己的转换例程。你可以抢一份 the C source for the Python struct module .
更新
发布文件格式细节后的评论:
字节顺序标记显然是可选的,但在文件开头除外。这很狡猾;它依赖于这样一个事实,即如果它不存在,则 block 的第 3 个和第 4 个字节是 header 字符串的第一个 2 个字节,并且既不是
'\x03\x04'也不是'\x02\x01'可以有效地开始一个标题字符串。明智的做法是读取 6 个字节——如果前 4 个是字节序标记,接下来的两个是 header 长度,而你的下一个读取是 header 字符串;否则向后查找 4 个字节,然后读取 header 字符串。以上属于滋扰类别。负尺寸是一个真正令人担忧的问题,因为它们指定了最大长度,并且没有提及实际长度是如何确定的。它说“然后逐行给出条目的实际大小”。如何?没有关于“数据行”是什么样子的文档。描述多次提到“线”;这些行是否由回车和/或换行符终止?如果是这样,如何区分换行符字节和属于当前数据“行”的 uint16 的第一个字节之间的区别?如果没有换行或其他什么,如何知道当前数据行何时完成?每个变量或其中的切片前面是否有一个 uintNN 大小?
然后它说上面的 (2)(负数)也适用于标题字符串。头脑难以置信。您是否有 (a) 标题字符串 (b) 数据“行”的“负大小”的任何示例(在文件布局文档中或在实际文件中)?
这种“确定的格式”是否公开可用,例如网络上的文档?格式是否有可搜索的名称?您确定您是世界上第一个想要阅读该格式的人吗?
阅读该文件格式,即使有完整的规范,也不是一件容易的事,即使对于有二进制格式经验且也使用过 Python(顺便说一句,Python 没有 float128)的人来说也是如此。您为这项任务分配了多少工时? (a) 延迟 (b) 失败的惩罚是什么?
您最初的问题涉及修复您尝试解析 uint16 的有趣方式——做更多的事情超出了 SO 问题的全部范围/意图。
