python - 如何使用 python 从 LTspice 解码压缩的二进制 .RAW 文件
问题描述
我正在尝试读取 .raw LTSPice 文件。在 LTSPice 的控制面板中,可以在 ASCII 和二进制压缩之间切换。ASCII 可读性没有问题,但它在大小和性能方面存在缺陷,这就是我想使用二进制压缩的原因。有可能选择二阶压缩,这就是目标。LTSpice 提供输出 .raw 文件,ASCII 文件具有电压和电流值,但在二进制文件中,有些符号我无法解码。
首先,我尝试使用 notepad++ 打开 .raw 文件。当我打开 ASCII .raw 文件和 UCS-2 Little Endian 打开二进制解压缩的 .raw 文件时,Notpad++ 显示在左下角的 UTF-8 中。我尝试了不同的编码,例如 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 的 Matlab 解决方案,LTSpice2Matlab( ltspice reader for Matlab),但我需要它用于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 文件中的内容(在文本“二进制:”之后):
栋㲚朎㲚鸞㕼鸞㕼鸞땼䕘퇠≄뻕襾㷨⁄㷨⡜㚾⡜㚾⡜뚾䕘퇠≄㻥䏨㹔ᙘ㹓㜬㜬뜬岓逇Ⳡ㻵◲㻇㯋㻃㞟㞟랟ጟ箽㼄籼㼯덌㼩Ӏ㠋Ӏ㠋Ӏ렋괄蝄㼎ڕ㽦럍㽢먵㠹먵㠹먵령귴脍侧㼑з㽴鍰㽲럜㡆럜㡆럜롆쵺튆㼒㽺땺㽹迀㡌迀㡌迀롌偵姏䰦㼔㽾枎㽽雈㡏雈㡏雈롏䰼ᬇⅤ㼖쵅㽿ᦊ㽾⢖㡐⢖㡐⢖롐暾좳죯㼗챭㽼錒㽺䕈㡍䕈㡍䕈롍얳✀礦㼚嘻㽰㽫㿃㡁㿃㡁㿃롁먬쬥㼞㽉뙵㽁낁㠞낁㠞낁렞袨�봜㼢睿㻔瘵㻄㞠㞠랠嘈䆬흞㼦㷧븥譻븠蒱뜃蒱뜃蒱㜃빝袏噥㼪뼝뼙㼆럼㼆럼㼆㟼玵嬆㼬ﵠ뽐】뽏멬렩멬렩멬㠩떋Ҕ덭㼭葔뽩뽨챢렾챢렾챢㠾넼ꧼ㼮쏐뽵뼃뽵傴롉傴롉傴㡉뮷惵㼯툡뽻뽻婇롎婇롎婇㡎�ﶻሣ㼰姢뽿ᚶ뽿롐롐㡐誔
我希望解码和阅读这个,我想我应该得到与 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 文件。
解决方案
当我打开 ASCII .raw 文件和 UCS-2 Little Endian 打开二进制解压缩的 .raw 文件时,Notpad++ 显示在左下角的 UTF-8 中。”
这很正常,UTF-8 是一种文本编码,它只是将一个字节序列与某个字符相关联。原始二进制文件没有固定的结构或编码,因为它们包含二进制数据:例如,考虑一下字符串"3.1415926535"
(在 UTF-8 中是 12 个字节)和该值的原始浮点二进制表示之间的差异(适合 4 个字节)。如果您将浮点数的“原始”4 字节解释为文本,您将得到一些垃圾文本输出或 unicode 解码错误。对于原始文件,特定的数据格式和每个字节的含义由生成它们的软件指定。
通常,您应该查找 LTSpice 原始文件规范,了解数据的排列方式并为此编写自己的解析器。但是因为这是 python,所以有人已经为你做了这个,并制作了一个你可以通过 安装的包pip
,查看那个包和它的例子,它应该很容易使用。
更新
在此链接中,他们声明原始二进制格式未正式披露,并且可能随时更改(尽管过去 15 年没有)。
格式本身是一个 UTF-16 标头,后跟原始二进制数据。当你说:
这是我目前在 LTSpice 的 .raw 文件中的内容(在文本“二进制:”之后):[...]
那是原始数据(以 UTF-16 解码,如您所见,这在文本中是无意义的)。该原始数据是按 header 中定义的顺序排列的变量值的打包列表,重复的时间点与数据中的时间点一样多。时间以双倍编码(即 8 个字节),其他任何东西 - 除非你也强制它加倍 - 是浮点数(4 个字节)。那么,你应该做的是:
1) 解析变量列表并计算一条记录有多长(例如,8 + 4*num_of_variables)
2)从“二进制”字符串中获取字节数据直到文件末尾,并将其拆分为您在步骤 1 中获得的长度的块
3) 相应地解释记录中的字节
推荐阅读
- json - 邮递员中 json 模式的 ajv 验证是错误的
- r - R url.exists 为不存在的 URL 返回 True
- ruby - Ruby:运行 rake 任务以执行 ruby 脚本
- typescript - 从联合中提取鉴别器值的类型
- python - 用硒打开的 Chrome 页面保持空白
- r - 如何读取多个 csv 并在每个文件名中保留数字?
- azure-media-services - azure 媒体服务直播中的 Stream Key
- vue.js - 在 vuetify 中隐藏选项卡标题
- javascript - 是否有一种惯用的 Javascript 方法可以避免为失败的 `Array.find()` 提供默认值?
- ios - 在具有多个联系人选择的反应本机应用程序中打开默认的 ios 联系人列表