ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

GDAL GeoJSONSeq 驱动详解:逐行解析 GeoJSON 特征序列(GeoJSONL/RS 分隔)格式

GDAL GeoJSONSeq 驱动详解:逐行解析 GeoJSON 特征序列(GeoJSONL/RS 分隔)格式 GIS遥感数据工程【免费下载链接】gdalGDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.项目地址https://gitcode.com/gh_mirrors/gd/gdal点击查看免费下载本文围绕 GDAL 的 GeoJSONSeq 矢量驱动展开讲解如何读取和创建以换行符LF或记录分隔符RS, 0x1E分隔的 GeoJSON Feature 序列文件.geojsonl/.geojsons覆盖驱动能力、三种数据源类型、配置项与全部图层创建选项LCO的默认值及底层行为并结合 驱动源码 与 测试用例 说明坐标重投影、追加写入、坐标精度控制等实现细节。一、GeoJSONSeq 是什么面向增量解析的 GeoJSON 序列格式GeoJSONSeq 驱动实现对逐个独立编码为 GeoJSON Feature 对象、以换行符LF,\n分隔即 Newline Delimited JSON或以记录分隔符 RS0x1ERFC 8142 定义的 GeoJSON Text Sequences 标准分隔的要素序列的读取与创建支持。文档原文geojsonseq.rst指出这类文件与一个 GeoJSON FeatureCollection 等价但对增量解析incremental parsing更友好。也就是说处理一个数十 GB 的要素集合时不需要把整个 FeatureCollection 载入内存再解析而是可以逐行/逐对象流式读取。这是该驱动存在的首要意义。从源码看驱动在 RegisterOGRGeoJSONSeq() 中注册声明的元数据确认了文档中的关键事实GDAL_DCAP_VECTOR YES、GDAL_DCAP_CREATE_LAYER YES、GDAL_DCAP_CREATE_FIELD YES、GDAL_DCAP_Z_GEOMETRIES YES支持带 Z 值几何GDAL_DMD_EXTENSIONS geojsonl geojsons即官方识别的两种文件扩展名GDAL_DCAP_VIRTUALIO YES支持 VSI 虚拟文件 IO如/vsigzip/、/vsimem/GDAL_DCAP_APPEND YES支持追加写入文档注明该能力自 GDAL 3.6 起可用GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION YES支持几何坐标精度设置见第四节GDAL_DMD_SUPPORTED_SQL_DIALECTS OGRSQL SQLITE支持的字段数据类型Integer、Integer64、Real、String、IntegerList、Integer64List、RealList、StringList字段子类型支持 Boolean。RS 分隔符在源码中即一行常量定义constexpr char RS \x1e;见 ogrgeojsonseqdriver.cpp。二、驱动能力Driver capabilities按文档标注该驱动支持以下能力对应源码中注册的元数据项能力说明源码依据supports_create可创建新数据源GDAL_DCAP_CREATE_LAYERsupports_georeferencing支持地理参考SRSICreateLayer中创建坐标变换supports_virtualio支持 VSI 虚拟文件系统GDAL_DCAP_VIRTUALIO YES此外还有文档未逐项列出但源码确认的能力追加写入AppendGDAL_DCAP_APPEND YES且图层在GA_Update访问模式下声明OLCSequentialWrite与OLCCreateField见 TestCapability()。SQL 查询元数据声明支持OGRSQL与SQLITE方言。无过滤器时支持快速要素计数OLCFastFeatureCount因为首遍扫描时已统计m_nTotalFeatures。三、数据源类型与识别规则Datasource文档指出驱动接受三类数据源URL——Web 地址执行 HTTP 请求带.geojsonl或.geojsons扩展名的纯文本文件GeoJSON 数据直接以文件名传入的文本且该文本编码为 GeoJSON 序列。并且可以用GeoJSONSeq:前缀消除歧义自 GDAL 3.10 起还可以用命令行工具的-if GeoJSONSeq选项或GDALOpenEx的papszAllowedDrivers只传GeoJSONSeq强制驱动识别所传 URL/文件名/文本。3.1 源码中的识别逻辑GeoJSONSeqGetSourceType() 实现了上述三类源的判定判定顺序是if (STARTS_WITH_CI(poOpenInfo-pszFilename, GEOJSONSeq:http://) || STARTS_WITH_CI(poOpenInfo-pszFilename, GEOJSONSeq:https://) || STARTS_WITH_CI(poOpenInfo-pszFilename, GEOJSONSeq:ftp://)) { srcType eGeoJSONSourceService; // GeoJSONSeq: 前缀 URL } else if (STARTS_WITH_CI(poOpenInfo-pszFilename, http://) || ...) { if (poOpenInfo-IsSingleAllowedDriver(GeoJSONSeq)) return eGeoJSONSourceService; // allowed_drivers 强制识别 if (IsLikelyESRIJSONURL(poOpenInfo-pszFilename)) return eGeoJSONSourceUnknown; // 让位给 ESRIJSON 驱动 srcType eGeoJSONSourceService; } else if (STARTS_WITH_CI(poOpenInfo-pszFilename, GEOJSONSeq:)) { // 先按文件统计VSIStatL判断否则按文本内容判断 ... } else if (GeoJSONSeqIsObject(poOpenInfo-pszFilename, poOpenInfo)) { srcType eGeoJSONSourceText; // 文本直接传入 } else if (GeoJSONSeqFileIsObject(poOpenInfo)) { srcType eGeoJSONSourceFile; // 普通文件 }几个值得注意的实现细节强制识别当allowed_drivers即papszAllowedDrivers/ 命令行-if中只包含GeoJSONSeq时IsSingleAllowedDriver(GeoJSONSeq)为真URL 类源不再返回不确定而直接按 GeoJSONSeq 打开——这就是文档中 specifying-if GeoJSONSeq... forces the driver 的源码体现。测试 test_ogr_geojsonseq_force_opening 验证了gdal.Open(filename, allowed_drivers[GeoJSONSeq])能打开一个常规识别会失败的.json序列文件且gdal.IdentifyDriverEx(http://example.com, allowed_drivers[GeoJSONSeq])返回 GeoJSONSeq 驱动。URL 会先下载整份内容Open() 中对eGeoJSONSourceService使用GeoJSONHTTPFetchWithContentTypeHeader拉取数据后放入/vsimem/隐藏临时文件再解析因此 URL 方式只读、不可更新GA_Update直接返回 false。3.2 看起来像 GeoJSON 序列的内容判定对无扩展名提示的文件/文本IsLikelyNewlineSequenceGeoJSON() 用一个小型状态机扫描内容在括号嵌套层级为 0 的位置若出现第二个顶层{且第一个对象关闭前曾遇到换行符则判定为 GeoJSON 序列返回GDAL_IDENTIFY_TRUE否则不确定GDAL_IDENTIFY_UNKNOWN。这解释了为何该格式的第一个对象可以是跨多行的pretty-printed JSON测试数据 test.geojsons 正是每个对象以 RS 开头、内部含换行的格式化输出而测试 test_ogr_geojsonseq_seq_geometries_with_errors 还验证了内容中混有foo、bar、null等非法行会被静默跳过只要存在合法 Feature/几何对象即可打开。读取时的逐对象解析在 GetNextObject() 中以固定大小缓冲区默认 40960 字节分块读文件在缓冲区内查找\n或首字节为 RS 时查找0x1E作为分隔符跨块时把半截对象累积到m_osFeatureBuffer直到对象完整再交给 JSON 解析器。因此单个 Feature 可以跨越任意多个读取块、任意大受下述OGR_GEOJSON_MAX_OBJ_SIZE限制。仓库中可直接查看的两份样例数据autotest/ogr/data/geojsonseq/test.geojsonl——LF 分隔{type:Feature,properties:{foo:bar},geometry:{type:Point,coordinates:[1,2]}} {type:Feature,properties:{foo:baz},geometry:{type:Point,coordinates:[3,4]}}autotest/ogr/data/geojsonseq/test.geojsons——RS036即八进制的0x1E分隔且对象为多行格式。四、配置项Configuration options文档声明该驱动仅有一个配置选项OGR_GEOJSON_MAX_OBJ_SIZE单位 MB限制单个可解析 JSON 对象的最大字节数。源码在 OGRGeoJSONSeqLayer 构造函数 中读取const double dfTmp CPLAtof(CPLGetConfigOption(OGR_GEOJSON_MAX_OBJ_SIZE, 200)); m_nMaxObjectSize dfTmp 0 ? static_castsize_t(dfTmp * 1024 * 1024) : 0;即默认 200 MB设为 0 表示取消限制。当累积的未闭合对象超过该上限时GetNextObject() 会报错并提示调大该选项。测试 test_ogr_geojsonseq_feature_large 构造了约 20 MB 的 Feature验证默认 200 MB 可打开、OGR_GEOJSON_MAX_OBJ_SIZE0.1约 0.1 MB时打开失败、设为0后再次成功。另有一个源码中注释为仅用于测试、未对外文档化的选项OGR_GEOJSONSEQ_CHUNK_SIZE读取块大小默认 40960 字节上限 100 MB见 ResetReading()测试 test_ogr_geojsonseq_seq_geometries 将其设为 10 字节来验证跨块读取的正确性。五、图层创建选项Layer Creation Options逐项解析文档列出的 LCO 全部在 RegisterOGRGeoJSONSeq() 的元数据 及 写入层构造函数 中有对应实现。逐项说明如下取值与默认值以文档和源码为准5.1RS取值YES/NO默认NO除非文件扩展名是geojsons。作用是否在每条记录前写入 RS0x1E字符使输出符合 RFC 8142GeoJSON Text Sequences。源码中创建数据源时按扩展名自动推断Create()m_bIsRSSeparated EQUAL(CPLGetExtensionSafe(pszName).c_str(), GEOJSONS);ICreateLayer再允许RSYES显式覆盖。写入时ICreateFeature()每条记录的实际落盘格式为[RS?]JSON\nchar chEOL \n; if ((m_poDS-m_bIsRSSeparated VSIFWriteL(RS, 1, 1, m_poDS-m_fp) ! 1) || VSIFWriteL(pszJson, strlen(pszJson), 1, m_poDS-m_fp) ! 1 || VSIFWriteL(chEOL, 1, 1, m_poDS-m_fp) ! 1) { CPLError(CE_Failure, CPLE_FileIO, Cannot write feature); eErr OGRERR_FAILURE; }测试 test_ogr_geojsonseq_lf、test_ogr_geojsonseq_rs、test_ogr_geojsonseq_rs_auto 分别验证了三种情形LF 模式文件首字节为{RSYES时首字节为\x1e创建.geojsons文件时即使不传选项也自动使用 RS 且内容中不出现}\n{这种 LF 分隔形态。5.2COORDINATE_PRECISION取值整数默认7未显式指定时使用。作用写入坐标时小数点后的最大位数并执行智能截断去除尾随零。写入层构造时同时作用于 XY 与 Z源码const char *pszCoordPrecision CSLFetchNameValue(papszOptions, COORDINATE_PRECISION); if (pszCoordPrecision) { m_oWriteOptions.nXYCoordPrecision atoi(pszCoordPrecision); m_oWriteOptions.nZCoordPrecision atoi(pszCoordPrecision); } else { m_oWriteOptions.nXYCoordPrecision atoi(CSLFetchNameValueDef(papszOptions, XY_COORD_PRECISION, 7)); m_oWriteOptions.nZCoordPrecision atoi(CSLFetchNameValueDef(papszOptions, Z_COORD_PRECISION, 3)); }注意XY_COORD_PRECISION/Z_COORD_PRECISION是驱动内部拆分后的选项ICreateLayer() 会把COORDINATE_PRECISION换算为分辨率10^-N并同步到两个内部选项也可由几何字段定义的精度设置自动推导见 5.5。测试 test_ogr_geojsonseq_COORDINATE_PRECISION 验证COORDINATE_PRECISION3时POINT(1.23456789 2.34567891 9.87654321)写入文件后为coordinates:[1.235,2.346,9.877]。5.3SIGNIFICANT_FIGURES取值整数默认17。作用写浮点数属性中的 Real 值时最多保留的有效位数。若显式指定了SIGNIFICANT_FIGURES而未指定COORDINATE_PRECISION它同样作用于坐标。对应写入选项m_oWriteOptions.nSignificantFigures源码。该选项与 GeoJSON 驱动共享同一套写入逻辑两者文档描述一致。5.4ID_FIELD与ID_TYPEID_FIELD指定一个源字段名其值将被写为 Feature 对象的id成员而不是留在properties中。ID_TYPEAUTO/String/Integer指定id成员的类型。实现位于m_oWriteOptions.SetIDOptions(papszOptions)写入层构造。这两个选项同样被 GeoJSON 驱动支持语义一致。5.5 几何坐标精度Geometry coordinate precisionGDAL 3.9文档专节说明创建时支持使用OGRGeomFieldDefn上的OGRGeomCoordinatePrecision设置用于把要素几何坐标舍入到合适的小数精度。两个要点COORDINATE_PRECISIONLCO 优先于OGRGeomFieldDefn上的设置文档 note 明确说明精度值不会序列化到生成的文件中因此读取时驱动不会通告几何坐标精度。源码印证了第一点ICreateLayer() 中先取COORDINATE_PRECISION只有它不存在时才回退到poSrcGeomFieldDefn-GetCoordinatePrecision()。并且由于驱动强制将几何重投影到 WGS84见第六节回退路径还会调用oCoordPrec.ConvertToOtherSRS(poSRS, oSRSWGS84)把源 SRS 下的分辨率换算为WGS84 下的分辨率再转为小数位数写入内部选项XY_COORD_PRECISION/Z_COORD_PRECISION。测试 test_ogr_geojsonseq_geom_coord_precision_not_4326 展示了这一换算在 EPSG:32631 下设置XY 分辨率 1 米重投影到 WGS84 后自动变成约8.98e-06对应 6 位小数最终坐标写为[2.363925,45.151706,9.877]而 test_ogr_geojsonseq_geom_coord_precision_already_4326 验证源 SRS 即 WGS84 时1e-5分辨率直接对应 5 位小数。5.6WRITE_NON_FINITE_VALUESsince 3.8取值YES/NO默认NO。作用是否写NaN/Infinity。这类值在严格 JSON 中不合法但某些 JSON 解析器例如 libjson-c 0.12因 ECMAScript 允许而能理解它们。对应m_oWriteOptions.bAllowNonFiniteValues源码。5.7AUTODETECT_JSON_STRINGSsince 3.8取值YES/NO默认YES。作用即使字符串字段的子类型subtype没有标记为 JSON只要它以方括号/花括号成对开头结尾就尝试将其解释为 JSON 数组或对象。对应m_oWriteOptions.bAutodetectJsonStrings源码。5.8WRITE_BBOXsince 3.10取值YES/NO默认NO。作用置YES时在 Feature 级别写入bbox成员值为该要素几何的边界框。对应m_oWriteOptions.bWriteBBOX源码。测试 test_ogr_geojsonseq_WRITE_BBOX 验证LINESTRING(2 49,3 50)写入后文件中出现bbox:[2.0,49.0,3.0,50.0]。六、创建时自动重投影到 WGS84 经纬度文档明确指出如果图层以其他 SRS 创建驱动会自动把几何重投影为 WGS84 经纬度。源码实现在 ICreateLayer()取图层 SRS与WGS84 传统 GIS 轴序东经, 北纬比较比较时忽略数据轴到 SRS 轴的映射差异若不同则创建OGRCoordinateTransformation存入写入层。实际重投影发生在每个要素写入时ICreateFeature()使用OGRGeometryFactory::transformWithOptions并带WRAPDATELINEYES选项与变换缓存m_oTransformCache缓存相同变换参数避免重复初始化 PROJ 上下文重投影后强制校验包围盒落在[-180, 180] × [-90, 90]内否则报错Geometry extent outside of [-180.0,180.0]x[-90.0,90.0] bounds并拒绝该要素——这是 GeoJSONRFC 7946 规定几何必须是 WGS84 经纬度格式约束的硬性保证。测试 test_ogr_geojsonseq_reprojection 直接验证以projmerc datumWGS84创建图层并写入墨卡托坐标POINT(222638.981586547 6242595.9999532)读回得到POINT (2 49)。此外创建图层时若完全未设置 SRS驱动会告警No SRS set on layer. Assuming it is long/lat on WGS84 ellipsoid并按 WGS84 处理。七、读取行为首遍扫描、字段合并与追加写入7.1 打开时的首遍扫描OGRGeoJSONSeqLayer::Init() 在打开读取时会完整扫描一遍文件逐个取对象、对每个 Feature 调用GenerateFeatureDefn合并字段定义字段顺序通过有向无环图拓扑排序保持稳定见 directedacyclicgraph.hpp同时统计m_nTotalFeatures。这意味着无过滤器时GetFeatureCount()是 O(1) 的直接返回缓存的m_nTotalFeatures见 GetFeatureCount()文件中的对象不要求全是 FeatureGetNextFeature() 还会接受裸几何对象包装成无属性 Feature并跳过 FeatureCollection 对象FID 缺省无id时按读取顺序分配递增 FIDm_nNextFID。7.2 追加写入GDAL 3.6以GA_Update方式打开已有文件即可向既有层追加要素ICreateFeature() 首次写入时把文件指针SEEK_END到末尾之后所有CreateFeature都是顺序追加追加的字段可通过CreateField补入仅追加到内存字段定义不改写已有行。创建新层数据源层在更新模式下声明ODsCCreateLayerTestCapability()新层要素同样直接追加到文件末尾文件因此变成多逻辑层的混排序列——按原层名过滤或读第一个层即可区分。测试 test_ogr_geojsonseq_lf 完整覆盖了这两条路径读模式打开时OLCCreateField/OLCSequentialWrite均不可用、写操作失败ogr.Open(filename, update1)后可CreateFieldCreateFeatureGetFeatureCount()从 2 递增到 3、4并可在同一文件上CreateLayer(new)再写一个要素。若更新模式下追加新层后调用GetNextFeature()源码会显式报错GetNextFeature() not supported when appending a new layer源码。另外注意 Create() 中的一个特殊处理/dev/stdout会被改写为/vsistdout/从而支持类似ogr2ogr ... /dev/stdout把 GeoJSON 序列直接输出到标准输出对不支持随机写的目标如/vsigzip/则以纯写模式wb打开。测试 test_ogr_geojsonseq_vsistdout 和 test_ogr_geojsonseq_vsigzip 分别验证了这两个场景。八、最小实战示例以 Python 绑定为例演示创建 追加 读取的完整闭环逻辑与 autotest/ogr/ogr_geojsonseq.py 的测试一致from osgeo import gdal, ogr, osr # 1) 创建 .geojsonl 数据源LF 分隔 ds ogr.GetDriverByName(GeoJSONSeq).CreateDataSource(/tmp/test.geojsonl) sr osr.SpatialReference() sr.SetFromUserInput(WGS84) lyr ds.CreateLayer(test, srssr, options[COORDINATE_PRECISION3]) # 坐标保留 3 位小数 lyr.CreateField(ogr.FieldDefn(foo)) f ogr.Feature(lyr.GetLayerDefn()) f[foo] bard # 含引号的字符串也能正确转义 f.SetGeometry(ogr.CreateGeometryFromWkt(POINT(1 2))) lyr.CreateFeature(f) ds None # 2) 以更新模式打开并追加 ds ogr.Open(/tmp/test.geojsonl, update1) lyr ds.GetLayer(0) f ogr.Feature(lyr.GetLayerDefn()) f[foo] baz f.SetGeometry(ogr.CreateGeometryFromWkt(POINT(3 4))) lyr.CreateFeature(f) ds None # 3) 读取也可直接传GeoJSONSeq:前缀、行内文本 ds ogr.Open(/tmp/test.geojsonl) print(ds.GetLayer(0).GetFeatureCount()) # 2 ds ogr.Open(GeoJSONSeq:/tmp/test.geojsonl) # 前缀强制指定驱动 ds ogr.Open({type:Feature,properties:{},geometry:null}\n {type:Feature,properties:{},geometry:null}) # 行内文本要点回顾扩展名为.geojsons时自动使用 RS 分隔需要 RS 但扩展名不是.geojsons时须显式RSYES源 SRS 非 WGS84 时几何自动重投影且必须能落入经纬度合法范围无扩展名/URL 内容不确定时用GeoJSONSeq:前缀或-if GeoJSONSeq/allowed_drivers[GeoJSONSeq]强制识别超大要素解析失败时调大OGR_GEOJSON_MAX_OBJ_SIZE单位 MB0为不限制。九、相关标准与延伸阅读文档给出的参考资料对应以下事实RFC 7946GeoJSON 格式标准Feature 必须为 WGS84 经纬度的根本依据RFC 8142GeoJSON Text SequencesRS 分隔标准同仓库的姊妹驱动 GeoJSONGeoJSON处理标准 FeatureCollection 文件驱动源码入口 ogr/ogrsf_frmts/geojson/ogrgeojsonseqdriver.cpp识别与工具函数在 ogrgeojsonutils.cpp完整测试在 autotest/ogr/ogr_geojsonseq.py。适用前提与限制小结追加写入自 GDAL 3.6 起可用WRITE_BBOX与WRITE_NON_FINITE_VALUES/AUTODETECT_JSON_STRINGS自 3.8 起可用-if强制识别与几何坐标精度3.9 起生效于写入、读取端不通告在较新版本中完整。若需处理超过默认 200 MB 的单对象文件、或强制打开模糊扩展名/URL请分别使用OGR_GEOJSON_MAX_OBJ_SIZE配置项与GeoJSONSeq:前缀/allowed_drivers机制。赞分享GIS遥感数据工程【免费下载链接】gdalGDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.项目地址https://gitcode.com/gh_mirrors/gd/gdal点击查看免费下载相关推荐时间序列特征提取全攻略tsfresh数据格式要求详解时间序列特征提取全攻略tsfresh数据格式要求详解 在当今数据驱动的时代 时间序列数据分析 已成为各行各业不可或缺的重要工具。无论是金融市场的股票价格预测特征工程机器学习数据分析GDAL RFC 65 深度解析GeoJSON 驱动如何写出 RFC 7946 标准的 GeoJSONGDAL RFC 65 深度解析GeoJSON 驱动如何写出 RFC 7946 标准的 GeoJSON GDAL 在 2.2 版本通过 RFC 65 httpGIS遥感数据工程时间序列特征提取终极指南tsfresh库80内置特征详解时间序列特征提取终极指南tsfresh库80内置特征详解 tsfresh是一个强大的Python库专注于从时间序列数据中自动提取相关特征。无论是进行时间序特征工程机器学习数据分析上一篇pandoc 命令测试精解RST figure 指令的 alt 文本回退与跨格式往返语义下一篇Textual CSS 类型系统完全指南从尖括号语法到内置类型的实战解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进