- 主题:在MS的xls中见到了史上最奇葩的设计
由于要parse老版本的*.xls文档,看了一下xls的格式,发现xls中存在一个极其奇葩的设计。
xls是Excel 97/95版本的,这种文件是二进制格式,带有一个文件头,文件头指向后面一系列的记录。
每个记录是T-L-V(Type-Length-Value)结构的,V里面会有很多结构,这个没啥问题。
由于每个记录有最大长度限制(Excel 97的记录的L最大值是8224字节,Excel 95是2080字节),
所以MS的人又搞了一个CONTINUE类型的记录,
一个超长的数据,会拆分为一个头部记录,外加一个或多个CONTINUE类型的记录。
这个拆分记录的设计,奇葩在什么地方?
一、在头部记录中,没有标志标明后面是否跟的有CONTINUE记录。
这样的话,拼凑这些记录的办法有:
1、一直向后预读,看是否存在CONTINUE记录,有则全部读进来拼成一块数据再解析。
流式解析的话,预读会降低效率,除非把预读的缓存着,而缓存后面的记录会增加复杂度。
但MS的人又搞了一个设计,导致你无法简单拼接记录。这个设计就是:
如果记录中的某个结构是字符串数据,这个结构将包含一个固定的头,用来表明字符串的长度、字符宽度等信息,固定头后面是变长的字符串数据。
如果要拆分记录时,正好是要从这个字符串结构这里拆开的话,它规定的拆分规则是:字符串的第一个字符一定要和其固定头保持在同一个记录中。
而且拆了字符串后,这个字符串处于下一个记录(CONTINUE记录)中的字符宽度是可以变的,比如8-bit的windows 1252编码的字符变为16-bit的utf16/GBK字符,或者反过来。虽然一般并不变。
也就是说被拆为两半的字符串,这两半的编码可以不一样!在CONTINUE记录的数据区的第一个字节,就是用来表明字符串的后一半的字符宽度的。但是就是因为这个字节的存在,导致无法简单拼接记录。因为如果不是从字符串结构的中间来拆分记录的话,不存在这个(重复的)字节。这个字节有时有,有时没有,那就难以简单处理。
2、先尝试解析前面的记录,直到发现必须要有CONTINUE记录才能满足解析要求,那么就记下中间状态,持续读取CONTINUE记录,根据中间状态继续解析,或者从头重试解析。
总的来说,因为这个奇葩设计,导致parser的复杂度大大增加。
--
FROM 125.35.123.*
所以后来要用xlsx啊,如果不是开始设计的太烂为啥要换新格式
--
FROM 101.93.79.*
是的,太烂了,有些是软盘时代的遗产(为了节省存储而大量使用奇葩的紧凑设计),
而且doc/ppt/xls这些老格式各自为阵,每个都不一样,明显是几个team单独搞的,没有统一规划
即便是docx/pptx/xlsx这些新格式,里面也有不统一的地方
【 在 Madlee 的大作中提到: 】
: 所以后来要用xlsx啊,如果不是开始设计的太烂为啥要换新格式
--
修改:z16166 FROM 125.35.123.*
FROM 125.35.123.*
这种东东不是有现成的吗?
Python 以前用过两个库,分别 xlrd, python-excel 能够分析 xls 和 xlsx
【 在 z16166 的大作中提到: 】
: 由于要parse老版本的*.xls文档,看了一下xls的格式,发现xls中存在一个极其奇葩的设计。
: xls是Excel 97/95版本的,这种文件是二进制格式,带有一个文件头,文件头指向后面一系列的记录。
: 每个记录是T-L-V(Type-Length-Value)结构的,V里面会有很多结构,这个没啥问题。
: ...................
--
FROM 47.243.39.*
python和java的不行,对性能有严格要求,类似杀软的实时防护扫描doc的要求,越快越好。
不过我上回遇到一个解开后xml有300多兆的xlsx,优化后还是要11秒,基本接近极限,只能从产品上想办法
【 在 hgoldfish 的大作中提到: 】
: 这种东东不是有现成的吗?
: Python 以前用过两个库,分别 xlrd, python-excel 能够分析 xls 和 xlsx
:
--
修改:z16166 FROM 125.35.123.*
FROM 125.35.123.*
Excel 项目组好像已经是MS内部项目管理标杆了
只能说技术债是利滚利的
【 在 z16166 的大作中提到: 】
: 是的,太烂了,有些是软盘时代的遗产(为了节省存储而大量使用奇葩的紧凑设计),
: 而且doc/ppt/xls这些老格式各自为阵,每个都不一样,明显是几个team单独搞的,没有统一规划
: 即便是docx/pptx/xlsx这些新格式,里面也有不统一的地方
: ...................
--
FROM 103.40.221.*
自己解析XLS文件? 够毅力!
GitHub上有C++的XLS读写库,在Qt上使用过。没测试过性能。
【 在 z16166 的大作中提到: 】
: 由于要parse老版本的*.xls文档,看了一下xls的格式,发现xls中存在一个极其奇葩的设计。
: xls是Excel 97/95版本的,这种文件是二进制格式,带有一个文件头,文件头指向后面一系列的记录。
: 每个记录是T-L-V(Type-Length-Value)结构的,V里面会有很多结构,这个没啥问题。
: ...................
--
FROM 110.87.79.*
只解析其中的子集。要是全部特性都解析,吐血也搞不完的。搞docx/pptx/xlsx还得花钱买OOXML的标准文档才能搞清全部细节
另外一个是RTF格式,这个格式明显是基于TeX搞的,必须要从头读到尾,不支持随机位置的读取。当然,早已经被MS抛弃了,只是提供兼容。
【 在 callmebbser 的大作中提到: 】
: 自己解析XLS文件? 够毅力!
: GitHub上有C++的XLS读写库,在Qt上使用过。没测试过性能。
:
--
FROM 125.35.123.*