如何使用python

时间:2019-10-16 08:36:02

标签: python binary compression decode

我正在尝试读取.raw LTSPice文件。在LTSPice的“控制”面板中,可以在ASCII和二进制压缩之间进行切换。 ASCII可以毫无问题地读取,但是它在大小和性能上都有缺点,这就是我要使用二进制压缩的原因。有可能选择二阶压缩,这就是目标。 LTSpice提供.raw文件作为输出,而ASCII文件具有电压和电流值,但是在二进制文件中,有一些我无法解码的符号。

首先,我尝试使用记事本++打开.raw文件。当我打开ASCII .raw文件时,Notpad ++在左下角显示为UTF-8;在打开二进制解压缩的.raw文件时,Notpad ++在UTF-2中显示。 我尝试使用其他编码,例如UTF-16le,ISO-8859-1 ...实际上我打印了所有编解码器并尝试使用它们:

import codecs
print(dir(codecs))

此外,我尝试不使用BOM。我发现了这一点,但对我没有任何结果:

import codecs
encoded_text = open('Circuit_binary_Transient.raw', 'rb').read()    #should read in binary mode to get the BOM correctly
bom= codecs.BOM_UTF16_LE                                      #print dir(codecs) for other encodings
assert encoded_text.startswith(bom)                           
encoded_text= encoded_text[len(bom):]                         #strip away 
decoded_text= encoded_text.decode('utf-16le')
print(decoded_text)

我发现Zlib是常见的压缩方式,我试图找出文件中哪些位置具有压缩功能,但结果却不尽人意。 我用过:

import zlib
from glob import glob

def zipstreams(filename):
    """Return all zip streams and their positions in file."""
    with open(filename, 'rb') as fh:
        data = fh.read()
    i = 0
    while i < len(data):
        try:
            zo = zlib.decompressobj()
            yield i, zo.decompress(data[i:])
            i += len(data[i:]) - len(zo.unused_data)
        except zlib.error:
            i += 1

for i, data in zipstreams("Circuit_binary_Transient.raw.raw"):
    print (i, len(data))

我总是得到len(data)的0。

我找到了这个脚本,但是没有执行二进制.raw文件解码:  http://www2.ee.unsw.edu.au/~tlehmann/ltspy.py
另外,我找到了Paul Wagner的LTSpice2Matlab解决方案,该解决方案由Paul Wagner(Matlab的ltspice阅读器)提供,但我需要用于python的解决方案,并且从该特定脚本中我找不到所使用的编码。我发现,对于二进制解压缩文件,Paul Wagner使用插值法获取了更多点,然后转换为可读格式。

实际上,我使用以下代码读取.raw文件:

data = fo.read() # Binary data read
fo.close()
line = str(data, encoding='utf-16le')
print(line)

当我使用ASCII .raw文件和UTF8时,结尾处是文本,但是当我使用二进制压缩的.raw文件时,我找不到如何以可读格式解码文件。

这是我目前在LTSpice的.raw文件中的内容(在文本“ Binary:”之后):

栋㲚朎㲚鸞㕼鸞㕼鸞땼䕘퇠≄뻕襾㷨⁄㷨⡜㚾⡜㚾⡜뚾䕘퇠≄㻥䏨㹔ᙘ㹓㜬㜬뜬岓逇Ⳡ㻵◲㻇㯋㻃㞟㞟랟ጟ箽㼄籼㼯덌㼩Ӏ㠋Ӏ㠋Ӏ렋괄蝄㼎ڕ㽦럍㽢먵㠹먵㠹먵령귴脍侧㼑з㽴鍰㽲럜㡆럜㡆럜롆쵺튆㼒㽺땺㽹迀㡌迀㡌迀롌偵姏䰦㼔㽾枎㽽雈㡏雈㡏雈롏䰼ᬇⅤ㼖쵅㽿ᦊ㽾⢖㡐⢖㡐⢖롐暾좳죯㼗챭㽼錒㽺䕈㡍䕈㡍䕈롍얳✀礦㼚嘻㽰㽫㿃㡁㿃㡁㿃롁먬쬥㼞㽉뙵㽁낁㠞낁㠞낁렞袨�봜㼢睿㻔瘵㻄㞠㞠랠嘈䆬흞㼦㷧븥譻븠蒱뜃蒱뜃蒱㜃빝袏噥㼪뼝뼙㼆럼㼆럼㼆㟼玵嬆㼬ﵠ뽐】뽏멬렩멬렩멬㠩떋Ҕ덭㼭葔뽩뽨챢렾챢렾챢㠾넼ꧼ㼮쏐뽵뼃뽵傴롉傴롉傴㡉뮷惵㼯툡뽻뽻婇롎婇롎婇㡎�ﶻሣ㼰姢뽿ᚶ뽿롐롐㡐誔

我希望对此进行解码和读取,并且我想我应该与ASCII .raw文件中的文件相同,例如:

0       0.000000000000000e+000  
    1.884843971540818e-002  
    1.884796850054908e-002  
    9.423984250366810e-007  
    9.423984250274539e-007  
    -9.423984250328532e-007  
1       3.951925877448456e-008  
    1.959322256186405e-002  
    1.959271263253092e-002  
    9.796356316741367e-007  
    9.796356316265457e-007  
    -9.796356317259836e-007  
2       1.185577763234539e-007  
    2.108275522427772e-002  
    2.108216492289399e-002  
    1.054108246213077e-006  
    1.054108246144700e-006  
    -1.054108246245633e-006

我将不胜感激。目的是读取压缩的.raw LTSpice二进制文件。

2 个答案:

答案 0 :(得分:1)

  

当我打开ASCII .raw文件时,Notpad ++显示在左下角UTF-8,而当打开二进制解压缩的.raw文件时,它显示在UCS-2 Little Endian中。”

这很正常,UTF-8是文本编码,它只是将字节序列与某个字符相关联。原始二进制文件没有固定的结构或编码,因为它们包含二进制数据:例如,考虑字符串"3.1415926535"(在UTF-8中为12个字节)与原始浮点二进制文件之间的区别该值的表示形式(适合4个字节)。如果将浮点数的“原始” 4个字节解释为文本,则将得到一些垃圾文本输出或unicode解码错误。对于原始文件,具体的数据格式以及每个字节的含义由生成它们的软件指定。

通常,您应该查找LTSpice原始文件规范,了解数据的排列方式,并为此编写一个解析器。但是,由于这是python someone already did that for you and made a package you can install via pip,因此需要查找该软件包及其示例,因此使用起来应该非常简单。


更新

this link,他们指出原始二进制格式尚未正式公开,并且可能随时出现变化(尽管最近15年来一直没有)。

格式本身是UTF-16标头,后跟原始二进制数据。 当你说:

  

这是我目前在LTSpice的.raw文件中的内容(在文本“ Binary:”之后):[...]

这是原始数据(在UTF-16上解码,如您所见,在文本中是无意义的)。该原始数据是按照标题中定义的顺序的变量值的打包列表,重复的时间与数据中的时间点相同。时间以 double (即8字节)编码,其他任何内容(除非您也强制将其加倍)都以 float (4字节)进行编码。 那么,您应该做的是:

1)解析变量列表并计算一条记录的长度(例如8 + 4 * num_of_variables)

2)从“二进制”字符串中获取字节数据,直到文件结尾,  并将其拆分为您在步骤1中获得的长度的大块

3)相应地解释记录中的字节

答案 1 :(得分:1)

可以使用UTF-16解码LTSpice的.RAW二进制文件的标头。如果尝试转换整个二进制RAW文件,则只有标题会转换为文本。使用UTF-16成功转换为文本的最后一个字符是“二进制:”。之后,应该获得“中文符号”或其他不可读的符号。

我使用了十六进制编辑器,并对同一电路的RAW ASCII文件和RAW二进制文件进行了比较。在ASCII文件中,可以找到“ Values:”而不是“ Binary:”,然后找到该十进制值。因此,可以借助十六进制编辑器将二进制代码与RAW ASCII文件中的实际值进行比较。

经过比较,我成功地解码了RAW二进制文件。下面写的所有内容均为十六进制。我有6个变量。这对以下域有效:DC扫描,DC op,瞬态和DC传输(用于AC分析和噪声始终为2 x 8字节双精度解码)。

  1. 在“二进制:”之后,总是有3个字节:00 0A 00(0A-换行);
  2. 然后有8个字节,如果将其转换为Double(float64)精度,则会给出正确的值;
  3. 然后我有4个字节,如果将其转换为Single(float32)精度,则会给出正确的值
  4. 给出一个值的4个字节重复5次(我有6个变量-标头“ No. Variables:”)
  5. 重复点2.,3和4.,直到满足标题中“编号点:”的数字为止。

我使用了LTSpice XVII。 另外,我使用了HxD十六进制编辑器https://mh-nexus.de/en/hxd/

编辑:非常重要:字节顺序是小端!!
这意味着对于十六进制的字节顺序-AA 77 B8 A2,应以相反的顺序进行转换-A2 B8 77 AA。 因此,以十进制转换的AA 77 B8 A2的单精度(float32)精度为-2.2e-13,以十进制转换的A2 B8 77 AA的精度为-5e-18。