Mapshaper 中的 GeoParquet 读写实战:列式矢量格式的导入导出、压缩选项与内存约束

📅 发布时间:2026/10/4 10:12:18
Mapshaper 中的 GeoParquet 读写实战:列式矢量格式的导入导出、压缩选项与内存约束
GISCLI数据可视化【免费下载链接】mapshaperTools for editing Shapefile, GeoJSON, TopoJSON and CSV files项目地址https://gitcode.com/gh_mirrors/ma/mapshaper点击查看免费下载GeoParquet 是一种将矢量几何与表格属性一并存储的紧凑列式格式已成为云原生地理数据交换的主流载体。本文以 Mapshaper 官方文档《GeoParquet》为骨架结合仓库中 导入实现 与 导出实现 的源码细节系统讲解 Mapshaper 读取与写出.parquet文件的行为规则、compression/level/rowgroup等输出选项的取值与语义以及大文件场景下的内存约束与规避策略帮助读者在 CLI 与 Web 端正确、高效地使用 GeoParquet。为什么选择 GeoParquet格式定位与适用场景GeoParquet 是一种紧凑的列式columnar二进制矢量格式把矢量几何与表格属性存放在同一文件中。它目前已成为云原生矢量数据的常见交换格式Overture Maps Foundation 的全球数据发布即采用 GeoParquetDuckDBspatial 扩展、GeoPandas、BigQuery、Athena、Synapse 等工具都能直接查询 GeoParquet 数据集。在 Mapshaper 中GeoParquet 的格式能力概览如下与 格式总览 中的对照表一致项目说明文件扩展名.parquet、.geoparquet读取支持写入支持图层数量不支持多图层一个文件对应一个图层几何编码读取时支持 WKB写出时统一为 WKB需要说明的是与 Shapefile、DBF、CSV 等格式不同GeoParquet 的文件编码固定为 UTF-8不受encoding选项影响参见 格式总览。快速上手三条 CLI 命令官方文档给出了一组最小可用的 CLI 示例覆盖读取信息、GeoParquet 转 GeoJSON、GeoJSON 转 GeoParquet三个典型场景# 查看 GeoParquet 文件的基本信息图层、几何类型、字段、CRS 等 mapshaper roads.parquet -info # 把 GeoParquet 转换为 GeoJSON mapshaper roads.parquet -o roads.geojson # 把 GeoJSON 转换为 GeoParquet mapshaper roads.geojson -o roads.parquetMapshaper 会根据文件扩展名自动推断输入输出格式因此通常无需显式声明format如需强制指定可在-i或-o上使用formatgeoparquet导出时formatparquet亦可作为别名这一点由 导出测试 验证。导出文件名默认取图层名加.parquet扩展名由于 GeoParquet 不支持多图层一个数据集内每个图层会各自写成一个文件。读取 GeoParquet输入行为与底层实现官方文档明确指出没有 GeoParquet 专属的-i输入选项。所有行为都来自导入器的默认逻辑可以从 mapshaper-geoparquet-import.mjs 的importGeoParquet()调用链中还原动态加载hyparquet库读取文件字节通过parquetMetadataAsync()解析 Parquet footer 元数据再调用parseGeoParquetMetadata()从 key-value 元数据中提取键为geo的 GeoParquet 元数据 JSON通过parquetReadObjects()以rowFormat: object逐行读出所有记录调用convertGeoParquetRows()把每一行转换为 GeoJSON Feature 并交给 GeoJSON 解析器最终构建出 Mapshaper 内部数据集。以下是导入时需要注意的几个行为细节。每个文件只导入一个几何列Mapshaper 每个文件只导入一个几何列当文件带有 GeoParquet 元数据时优先使用primary_column指定的列若该列不存在或不是 WKB 编码则回退到第一个 WKB 编码的几何列完全没有元数据时则查找名为geometry的列或通过对象带有type字符串的启发式规则识别 GeoJSON 式几何。文件中额外的几何列目前会被忽略不会报错也不会进入属性表。仅支持 WKB 编码原生编码降级为纯属性导入几何列必须使用WKBWell-Known Binary编码。若文件中只有原生native编码而没有 WKB 列导入器会发出一次性警告Unable to import GeoParquet geometry: native encodings are not supported (expected WKB). Importing attribute data only.随后仅导入属性数据图层几何类型为 null。这一点由 导入测试 用data-point-encoding_native.parquet固定样本验证4 条记录全部导入但geometry_type为 null。仓库的 测试数据目录 中同时准备了 point / linestring / polygon / multipoint / multilinestring / multipolygon 的 native 与 wkb 两种编码样本可直接用于对比验证。属性值规范化BigInt 与精度警告Parquet 的整数可能以 JavaScript 无法精确表示的 BigInt 形式读回。导入器会对属性值做递归规范化normalizeGeoParquetValue安全范围内的 BigInt 直接转为 Number超出Number.MAX_SAFE_INTEGER或超出双精度范围的值会发出precision will be lost警告后截断转换。测试用例分别覆盖了42n 无警告转换与9007199254740993n 丢失精度并警告两种情形。CRS从元数据解析坐标参考系导入器会把geo元数据中几何列的crs解析为 Mapshaper 内部可用的crs_string写入dataset.info.crs_string并同时保留dataset.info.geoparquet_geo与dataset.info.geoparquet_crs供后续使用。解析策略getGeoParquetCrsStrings是若 CRS 带有 EPSG 或 ESRI authority 标识优先构造epsg:XXXX/esri:XXXX字符串否则尝试用mproj库把 PROJJSON 转换为 Proj4 字符串全部失败时发出 Unable to import CRS from GeoParquet metadata 警告。一个关键实现细节不会把base_crs当作投影 CRS 的标识——base_crs是投影所基于的地理 CRS用它替换缺失的顶层id会把投影坐标误读为经纬度源码注释 与 导入测试 均明确说明。此外导入测试还验证了 EPSG 查询失败时自动回退到 PROJJSON→Proj4 的容错路径。写出 GeoParquet输出行为与底层实现导出的核心实现在 mapshaper-geoparquet-export.mjs 的exportGeoParquet()中逐图层构建列式数据把每行的 GeoJSON 几何交给hyparquet-writer编码为 WKB以行组row group为单位分块写出。统一的 WKB 几何列与类型推断写出时固定使用一个名为geometry的 WKB 几何列属性列的类型由inferColumnType()逐行采样推断布尔→BOOLEAN安全范围内的整数→INT32其余有限数→DOUBLEDate→TIMESTAMP字节缓冲→BYTE_ARRAY数组/对象→JSON其余→STRING同一列出现 INT32 与 DOUBLE 混用时提升为DOUBLE出现不可调和的分歧时降级为STRING。测试断言了导出 schema 为geometry: BYTE_ARRAY, name: BYTE_ARRAY, count: INT32, ratio: DOUBLE, flag: BOOLEAN导出测试。图层无几何时若仍有属性则照常导出为纯 Parquet 表伴随 writing attribute data only 警告几何与属性皆无或零记录时会直接报错GeoParquet export requires at least one record/GeoParquet export requires geometry or attribute data。CRS 双重写入geo 元数据 GEOMETRY 逻辑类型若图层带有 CRS导出器会把它同时写入两处buildSchemaGeoParquet 的geo元数据版本1.1.0primary_column: geometryencoding: WKB含geometry_types与crsParquet 2.11 引入的GEOMETRY逻辑类型logical_type: {type: GEOMETRY, crs: ...}。原因在于支持 GEOMETRY 逻辑类型的读者会忽略geo元数据而逻辑类型不带 CRS 时规范默认按OGC:CRS84处理会把投影数据误报为 WGS 84。双写是 GDAL 的通行做法可让 GeoParquet 1.x 读者继续正常工作导出测试 验证了两处 CRS 一致。CRS 来源优先取导入时保留下来的geoparquet_crs否则通过mproj把crs_string或 WKT 转换为 PROJJSON。导入测试也验证了 Vermont UTMepsg:32618样本可以无损往返。行组规划按字节而非按行数分块行组大小由字节预算而非行数决定planRowGroups点几何一行仅几十字节而高细节多边形一行可达数万字节按固定行数切分会带来上百倍的偏差。实现要点单行大小通过对图层等间隔采样默认 1000 行估算采样按步长散布而非取前缀避免排序/聚集数据造成偏差目标行组约16 MBROW_GROUP_TARGET_BYTES行数上限 100 万行文件开头额外留一个约1 MB的小预览组ROW_GROUP_PREVIEW_BYTES便于 HTTP 范围读取的读者快速看到表头数据剩余行会均匀分摊到后续行组避免末尾出现袖珍组导出采用逐行组转换、随写随弃的策略GeoJSON→WKB 的临时内存占用只与行组大小相关而不是整个图层的大小源码注释。行组规划测试 对这一策略做了系统验证小图层单组、大几何自动拆分、预览组保持约 1 MB、行数上限 100 万、单行超预算时仍能逐行推进。地理统计边界修正与 pyarrow/GDAL 的兼容性导出器还会修正行组地理统计中的 bbox 边界avoidIntegerBboxBoundshyparquet-writer会根据运行时值推断 thrift 线类型若 bbox 边界恰好落在整数上会被写成 I32而 Parquet 规范要求 double——pyarrow 21、GDAL 3.11 等解析地理统计的读者会因此无法反序列化 footer直接打不开文件。实现通过位级步进把整数边界外扩到相邻 double宁大勿小只影响读者跳过行组的收益超过 2^53 无法步进时则删除该 bbox。地理统计测试 断言所有行组的 bbox 边界均非整数且仍覆盖全部点。通用输出选项的配合-o的通用选项同样作用于 GeoParquet例如precision会先对坐标取整再编码取整后几何坍缩为空的要素仍保留在属性表中、几何列写为 null导出测试。另外被hoist提升到 GeoJSON Feature 根部的属性不会成为 Parquet 列getPropertyNames。输出选项详解compression、level 与 rowgroup官方文档列出的 GeoParquet 专属输出选项有两个CLI 选项注册见 mapshaper-options.mjs此外源码还支持第三个rowgroup选项。compressionsnappy|zstd|none选择 Parquet 列压缩算法默认snappysnappy压缩与解压速度快压缩比中等适合读写频繁的场景zstd压缩更慢但通常文件更小适合以文件大小为首要目标的情形例如发布下载包或存入云存储桶none写出未压缩的 Parquetuncompressed亦可作为等价取值。底层由 normalizeGeoParquetCompression 校验未知取值会直接报错测试确认compressionzstd写出文件的列编码为ZSTD、compressionnone为UNCOMPRESSED。浏览器端与 Node 端分别通过bokuweb/zstd-wasm的运行时加载与动态 import 提供 ZSTD 压缩器mapshaper-gui-geoparquet.mjs 在 Web 端注册了hyparquet、hyparquet-compressors、hyparquet-writer与 zstd-wasm 四个模块。levelZSTD 压缩级别仅在使用compressionzstd时有效取值必须是1 到 22 的整数省略时使用 ZSTD 库默认级别。校验逻辑在 validateGeoParquetCompressionLevel在非 zstd 压缩下指定level会报错 The level option only applies with compressionzstd导出测试 验证。另有一个实现细节当级别 ≥ 10 时输出 page size 会固定为 64 KBgetGeoParquetPageSize。若某页压缩失败通常因级别过高会提示降低level值。# 以 ZSTD 压缩、级别 10 写出 mapshaper roads.geojson -o formatgeoparquet compressionzstd level10 # 写出未压缩的 GeoParquet mapshaper roads.geojson -o roads.parquet compressionnonerowgroup手动指定每行组行数源码还提供了文档未展开的第三个选项rowgroup描述为 [GeoParquet] rows per row group (default: sized by data)。取值为正整数行数不指定时按上文按字节规划的默认策略分块。校验逻辑要求rowgroup 1且为整数否则报错 The rowgroup option must be a positive integer number of rows。测试用例rowgroup250会把 1000 行切成 4 个 250 行的行组导出测试。# 每个行组固定 250 行 mapshaper roads.geojson -o formatgeoparquet rowgroup250内存与规模大文件处理建议官方文档特别强调GeoParquet 没有固定的文件大小上限限制主要来自内存。常规 CLI上限即 Node 的堆大小。处理超大文件时改用mapshaper-xl它默认以8 GB 堆启动并可进一步调大例如mapshaper-xl 16gb ...。Web 应用非常大的导入通常取决于浏览器/设备几百 MB 的量级可能耗尽内存导致标签页崩溃。因此大 GeoParquet 文件请优先使用 CLI /mapshaper-xl。这一约束与导出端整个数据集常驻内存、写出约需输出体积二十倍内存的实现行组规划源码注释互为印证行组规划的 16 MB 目标正是为了在单机内存模型下给读者保留并行度与过滤跳过的空间。支持范围小结能力状态与说明扩展名.parquet、.geoparquet自动识别可用format覆盖读取几何编码仅 WKB原生编码降级为纯属性导入并警告写入几何列单列、固定名为geometry的 WKB多图层不支持一个文件一个图层压缩snappy默认/zstd/noneZSTD 级别level1–22行组大小rowgroup指定行数默认按字节预算自动规划CRS导入解析 EPSG/ESRI 或 PROJJSON→Proj4导出双写 geo 元数据与 GEOMETRY 逻辑类型大文件常规 CLI 受 Node 堆限制建议mapshaper-xl 16gbWeb 端几百 MB 可能崩溃进一步探索格式对照总览docs/formats/overview.md导入源码src/geoparquet/mapshaper-geoparquet-import.mjs导出源码src/geoparquet/mapshaper-geoparquet-export.mjs导入测试test/geoparquet-import-test.mjs导出测试test/geoparquet-export-test.mjs测试样本test/data/geoparquet含 WKB/native 双编码的 point、linestring、polygon 及 multipoint/multilinestring/multipolygon 样本Vermont CRS 系列样本ZSTD 压缩样本sample-zstd.parquet等命令行选项定义src/cli/mapshaper-options.mjs另外说明Mapshaper 的 GeoParquet 导入基于hyparquet库实现写入基于hyparquet-writerWeb 端通过 mapshaper-gui-geoparquet.mjs 打包对应模块更完整的格式规范与几何逻辑类型细节可参阅官方 GeoParquet 规范与 Apache Parquet 的 Geospatial 逻辑类型说明。赞分享GISCLI数据可视化【免费下载链接】mapshaperTools for editing Shapefile, GeoJSON, TopoJSON and CSV files项目地址https://gitcode.com/gh_mirrors/ma/mapshaper点击查看免费下载相关推荐Home Assistant Blue Current 集成使用 blue_current.start_charge_session 动作远程启动充电会话Home Assistant Blue Current 集成使用 blue_current.start_charge_session 动作远程启动充电会话 本GISCLI数据可视化PPT Master把任意文档变成可完全编辑的 PowerPointPPT Master把任意文档变成可完全编辑的 PowerPoint PPT Master 是一个开源的 AI PPT 生成工作流给它一份 PDF、WordAI 技能人工智能AI 应用旧Mac升级系统一台2015款MacBook Pro免费续命Sequoia的全过程实录旧Mac升级系统一台2015款MacBook Pro免费续命Sequoia的全过程实录 如果你手头有一台被苹果官方系统支持列表除名的Mac别急着判它死刑操作系统固件驱动开发上一篇2024终极RAG技术实战指南从本地部署到智能问答系统构建下一篇CANN/ge图引擎APIIsGraphNeedRebuild函数创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考