如何读取Shapefile(第一部分)

1,583 阅读2分钟

读取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 小实验

图片.png

通过图片可以看到第一位是大字节序,前四位,
我们使用如下代码测试

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 符合预期

如下图所示,代码调试成功。

图片.png

参考链接:
1 node.js #buffer
2 MDN Endianness
3 MDN ArrayBuffer 4 MDN TypedArray
5 MDN DataView