自定义四维二进制格式
现有格式存在的问题
经常被用来保存气象数据的格式已经非常多,如nc、grib、hdf、micaps等等,为何我们我们还要定义新的数据存储格式呢?
这主要是因为咱们的应用通常运行于浏览器端,数据从服务器到看到要经过后端解码筛选、网络传输、前端解析、前端渲染这几个阶段,这样的场景要求我们的数据必须要能够快速的被获取、快速的传输、快速的解码,而传统的数据格式定义在很多时候无法同时满足这些要求,如:
- GRIB/NC格式被大量用于存储数值模式输出结果,而这个格式定义非常灵活,目前还没有解码器能够直接在浏览器对该格式进行完美解码,自行编写编码器设计的依赖库众多,也不是一个短期能够完成的任务,后端实时解码又会降低数据获取的效率。
- Micaps/MUSIC等文本格式虽然简单易懂,但是如果精细化的网格数据直接文本存储会造成尺寸过大,传输过慢,而且前端也需要二次解析,但是对于内网高带宽应用也是合适的。
- OPeNDAP数据规范是为数不多的比较适合的开箱即用的数据服务系统,但是由于其为了支持各类投影,在返回数据时同步返回了经纬度网格的二维场,大大增加了数据传输量,但不失为一个极好的内网数据服务端。
新的数据格式
为了解决以上问题,我们针对前端渲染的需要定义了一个新的简单的数据格式,具体如下:
ZIP(文件头JSONString长度(int)+JSONString+DATA[t,z,y,x])
格点数据首先是4个字节的整型,表示JSONString区域的长度(不含该整型4字节本身), 然后是JSON转成二进制字符串的头文件部分,头文件具体格式见头文件部分。
最后是数据部分,数据部分首先保存第一个时次的第一个层次的二维数据场,数据场中纬度在外层,经度在内层,如下所示: data[time][level][y][x]
最后为了缩小文件尺寸的同时保证前端解压效率,使用zip格式进行存储。
头文件长度
前四个字节是头文件区域的长度,是四个字节的int,不包括自身。
头文件描述
示例
{
"xStart": 112.35,
"yStart": 36.0,
"xDelta": 0.025,
"yDelta": 0.025,
"xSize": 307,
"ySize": 301,
"xEnd": 120.0,
"yEnd": 43.5,
"times": 3,
"levels": 3,
"timestamp": 1595574600,
"levelList": [
"150",
"450",
"750"
],
"timeList": [
"0",
"10",
"20"
],
"dataType": "Int8",
"undef": 255.0,
"dataScale": 1.0,
"dataOffset": 0.0,
"units": null,
"littleEndian": true,
"properties": {},
"unsigned": true
}
关键字名 | 类型 | 描述 |
---|---|---|
xStart | float | 起始经度 |
yStart | float | 起始纬度 |
xEnd | float | 结束经度 |
yEnd | float | 结束纬度 |
xDelta | float | 经度间隔 |
yDelta | float | 纬度间隔 |
xSize | int | 经度格点数 |
ySize | int | 纬度格点数 |
times | int | 时间个数 |
levels | int | level个数 |
timestamp | long | 时间 |
levelList | 数组 | 层级数组,单位是米,如果是其他单位,在使用前前端需要先预处理为米 |
timeList | 数组 | 时间(毫秒时间戳)数组,用于业务系统识别时间,框架本身不用 |
dataType | string | Int8或Int16或Int32或Float32 |
undef | float | 缺省值 |
dataScale | float | 数据的缩放倍数,比如数据已经被放大了2倍再存储,则该值存储为0.5(即数据精度为0.5)。在存储时,存储值=(原始值-offset)/scale如雷达有效反射率可能在-30~100之间,希望能够存储到0.5的精度,就可以将offset设置为-30,scale设置为0.5,然后通过上述公式算出实际存储值,这时候的存储值即可用uint8来表示(dataType=”Int8”,unsiged=true),以便节约存储空间。 |
dataOffset | float | 数据的偏移量,比如数据增加了66再存储,则该值为-66 |
units | string | 单位 |
littleEndian | boolean | 保持为true,暂时不支持大端 |
unsigned | boolean | 无符号为true,否则为false |
properties | Map对象 | 自由数据 |
数据区域
数据区域支持四个维度,其中时间在最外层,接下来是层次,然后是纬度,最后是经度。其中时间和层次可以只有一个时次和一个层次。
使用示例
该类数据格式在框架中由QEGridDataProvider
负责解析,具体使用示例如下:
No Comments