读取Shapefile第一部分
本系列分为两部分第一部分,跑通基本技术路线,分析遇到的知识点。第二部分把读取数据中遇到的坑展示出来。
1 知识点
我选择用node.js 读取shapefile文件,工作量分为两部分:1 如何读取二进制文件 2 具体二进制格式解析。
1.1 ArrayBuffer
ArrayBuffer用来表示通用的、固定长度的原始二进制数据缓冲区,必须通过TypedArray或者DataView来访问。
1.2 TypedArray
TypedArray是一个类型化数组用来读取二进制对象,它可以说是视图(view)。它本身不支持构造器,是通过他的一系列子集来生成对象的。例如:Uint8Array 。
1.3 Node.js Buffer
Buffer 被用来表达读取的二进制对象。它是 Uint8Array 的子集。这里要注意他的每一位是8个字节(bit)。
本身Buffer就是Uint8Array的实例,Uint8Array也是TypedArray的实例,因此TypedArray可以在node.js中使用,但是它和Buffer有几个区别。
- TypedArray#slice() 创建了一个TypedArray的拷贝,Buffer#slice() 没有拷贝而是创建了视图。
- TypedArray#subarray()可用于实现 Buffer#slice()在Buffers和其他TypedArrays上的行为(仅在旧版的兼容性,可能会产生意外)。
- buf.toString() 与它在 TypedArray 上的等价物并不兼容
- 部分方法,例如 buf.indexOf(),支持额外的参数。
1.4 DataView
也是读取二进制数据的一种展示视图,不过它存在支持字节序的方法,初始化相对麻烦。
1.5 SHP 如何读取
shapefile 通过ESRI的白皮书读取,里面描述了相关格式。
1.6 字节序问题
developer.mozilla.org/zh-CN/docs/…
字节序也就是数据的存储顺序,具体参见MDN链接,shapefile文件大小字节序都有,这一点要注意。
1.7 Buffer和TypedArray 如何互转
1 Buffer to TypedArray
const buf = Buffer.from('hello', 'utf16le');
const uint16arr = new Uint16Array(
buf.buffer, buf.byteOffset, buf.length / Uint16Array.BYTES_PER_ELEMENT);
2 TypedArray to buffer
const arr = new Uint16Array(20);
const buf = Buffer.from(arr.buffer, 0, 16);
console.log(buf.length); //16
2 小实验
通过图片可以看到第一位是大字节序,前四位,
我们使用如下代码测试
const fs = require("fs")
const buffer = fs.readFileSync('./data/宝鸡数据/宝鸡数据.shp');
const a = buffer.readUIntBE(0,4);// readUIntBE 参数1 从第几位开始 参数2 读取几字节
console.log("a",a) // a = 9994 符合预期
如下图所示,代码调试成功。
参考链接:
1 node.js #buffer
2 MDN Endianness
3 MDN ArrayBuffer
4 MDN TypedArray
5 MDN DataView