☰
GDAL (Geo)Arrow 矢量驱动完全指南:Feather/Arrow IPC 格式的读写、配置与源码剖析
2026/10/12 1:52:08 网站建设 项目流程
  • GIS
  • 遥感
  • 数据工程

【免费下载链接】gdal

GDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.

项目地址:https://gitcode.com/gh_mirrors/gd/gdal
点击查看免费下载

(Geo)Arrow IPC File Format / Stream(即 Feather 格式家族)是 Apache Arrow 生态中用于存储 Arrow Table 或数据框(如 Python/R 中常见的数据框对象)的便携式文件格式,内部基于 Arrow IPC 协议。GDAL 自 3.5 起通过Arrow 矢量驱动原生支持该格式的两种变体(随机访问的 File 格式与流式的 Streaming IPC 格式),并在 3.9 起完整支持 GeoArrow 几何列规范。本文将以官方驱动文档为主体,结合 GDAL 仓库中的驱动实现源码与自动化测试,系统讲解该驱动的格式背景、打开与识别机制、创建选项、几何编码、安装部署与源码级实现原理,帮助你直接用 GDAL/OGR 读写 Feather/Arrow 文件,并理解其底层工作方式。

一、格式背景:Arrow IPC 的两种变体

Arrow IPC 格式本质上是一套列式二进制布局的封装协议。GDAL Arrow 驱动支持其两种变体(官方文档定义):

  • File / Random Access 格式(又名 Feather):用于序列化固定数量的 Record Batch(记录批次)。读取此类文件需要随机访问能力,但生成端只需具备流式写入能力即可。推荐扩展名为.arrow。GDAL 驱动元数据中注册的扩展名为arrow feather arrows ipc(见 ogrfeatherdrivercore.cpp)。
  • Streaming IPC 格式:用于发送任意长度的 Record Batch 序列,一般必须从头到尾顺序处理,不需要随机访问。该格式通常不物化为文件;若物化,推荐扩展名为.arrows(注意带尾字母 s)。驱动同时支持普通文件以及/vsistdin/、/vsistdout/这类流式虚拟文件。

两种变体的差别在读取路径上体现为使用不同的 Arrow 读取器:驱动源码在打开文件时,流式格式走arrow::ipc::RecordBatchStreamReader::Open(),文件格式走arrow::ipc::RecordBatchFileReader::Open()(见 ogrfeatherdriver.cpp);在写入路径上则分别调用arrow::ipc::MakeStreamWriter()与arrow::ipc::MakeFileWriter()(见 ogrfeatherwriterlayer.cpp)。

提示:本驱动同时支持几何列(GeoArrow 规范),但官方文档明确标注:该驱动应视为实验性功能,因为 GeoArrow 规范尚未最终定稿。

二、打开与格式识别机制

1. 自动识别策略

驱动打开文件时,通过Identify()逻辑判定内容属于哪种变体(实现见 ogrfeatherdrivercore.cpp):

  • File 格式:校验文件头尾是否都有 6 字节签名"ARROW1",并解析文件末尾 4 字节的 footer 大小字段(见OGRFeatherDriverIsArrowFileFormat(),ogrfeatherdrivercore.cpp)。
  • Stream 格式:先检查头部是否以0xFFFFFFFF连续标记(4 字节)+ 4 字节元数据长度开头;若扩展名为arrows或ipc则直接判定;否则进一步用RecordBatchStreamReader::Open()尝试解析(见 ogrfeatherdriver.cpp)。

2. 流式格式识别的难点与强制手段

官方文档指出:打开时驱动可能难以识别内容是否为 Arrow IPC 流,尤其是扩展名不是.arrows、且元数据段很大时。为此文档提供三种强制打开方式:

  • 文件名前缀ARROW_IPC_STREAM::例如ARROW_IPC_STREAM:/vsistdin/,驱动将无条件按流式 IPC 格式打开。注意前缀后跟的路径才是真实文件名,驱动会剥离此前缀后按原路径打开(ogrfeatherdriver.cpp)。
  • GDAL 3.10 起:命令行工具中传入-if ARROW。
  • GDAL 3.10 起:在GDALOpenEx的papszAllowedDrivers中仅指定ARROW一个值,也强制驱动识别该文件名。

其中ARROW_IPC_STREAM:前缀在流式文件的随机访问/回退能力上有专门处理:驱动据此判断流是否可 seek(bSeekable),/vsistdin/与ARROW_IPC_STREAM:打开的流被标记为不可回退,FeatureCount 快速统计、rewind 等操作会受到限制(对应测试见 ogr_arrow.py)。

3./vsistdin/的特殊处理与 1 MB 限制

源码中针对/vsistdin/有一个值得注意的实现细节:由于标准输入无法回退超过首个 1 MB,当头部元数据段超过约 1 MB 时,驱动无法自动识别流式内容,此时必须通过ARROW_IPC_STREAM:前缀或allowed_drivers=["ARROW"]强制打开(ogrfeatherdrivercore.cpp)。自动化测试test_ogr_arrow_ipc_read_stdin专门构造了一个元数据超过 1 MB 的流式文件,验证了"默认无法打开、指定 allowed_drivers 后可打开"的行为(ogr_arrow.py)。

4. 打开限制

  • 不支持更新:OGRFeatherDriverOpen()中对GA_Update直接返回nullptr(ogrfeatherdriver.cpp)。
  • 支持虚拟 IO(GDAL_DCAP_VIRTUALIO = YES),因此/vsi*路径均可读写。

三、Open Options(打开选项)

官方文档定义的唯一打开选项如下:

选项取值默认值引入版本说明
LISTS_AS_STRING_JSONYES/NONO3.12.1是否将字符串/整数/实数列表字段报告为String(JSON)字段,而不是String/Integer[64]/RealList列表类型

该选项的核心价值在于空值语义的精确映射:当列表中存在 null 值时,默认的列表类型映射会"省略"空字符串(字符串列表)或"置 0"(布尔/整数/实数列表),而YES模式能原样保留 null 值。驱动在注册元数据时同步生成了该选项的 XML 定义(ogrfeatherdrivercore.cpp),测试test_ogr_arrow_lists_as_string_json验证了开启后[null,false,true,false]、[null,7,8,9]等空值被完整保留(ogr_arrow.py)。

四、创建能力与限制

驱动支持创建(GDAL_DCAP_CREATE = YES、GDAL_DCAP_CREATE_LAYER = YES),但每个数据集只能创建单层。这一点在写入端有硬性约束:ICreateLayer()中若m_poLayer已存在,直接报错"Can write only one layer in a Feather file"(ogrfeatherwriterdataset.cpp)。

字段能力方面,驱动注册支持Integer Integer64 Real String Date Time DateTime Binary IntegerList Integer64List RealList StringList等创建字段类型,以及Boolean Int16 Float32 JSON UUID字段子类型(ogrfeatherdrivercore.cpp)。值得注意的元数据还包括:

  • GDAL_DCAP_MEASURED_GEOMETRIES = YES与GDAL_DCAP_Z_GEOMETRIES = YES:支持 M / Z / ZM 维度几何(默认仅 2D,可用配置项OGR_ARROW_ALLOW_ALL_DIMS=YES放开,见 ogrfeatherwriterlayer.cpp)。
  • GDAL_DCAP_REOPEN_AFTER_WRITE_REQUIRED = YES:写入完成后需重新打开才能读取。

五、Layer Creation Options(图层创建选项)

这是驱动最核心的实操参数,官方文档定义如下,下面逐项结合源码展开。

1.COMPRESSION— 压缩方法

  • 取值:NONE、ZSTD、LZ4。
  • 默认值:Arrow 库编译时支持 LZ4 则用LZ4,否则NONE。
  • 说明:可选值取决于 Arrow 库的编译情况。驱动在注册元数据时通过arrow::util::Codec::GetCompressionType()+Codec::IsAvailable()动态探测可用压缩器,生成LayerCreationOptionList时只列出实际可用的取值(ogrfeatherdriver.cpp)。写入时若显式指定了不支持的压缩方法会直接报错(ogrfeatherwriterlayer.cpp)。
  • 源码细节:NONE在内部会被转换为UNCOMPRESSED传给 Arrow 编解码器,且 XML 选项中NONE带有UNCOMPRESSED别名。

2.FORMAT— 格式变体

  • 取值:FILE、STREAM。
  • 默认值:FILE,除非文件名是/vsistdout/或其扩展名是.arrows,此时默认STREAM。

源码中的默认值判定逻辑如下(ogrfeatherwriterlayer.cpp):

const char *pszDefaultFormat = (EQUAL(CPLGetExtensionSafe(osFilename.c_str()).c_str(), "arrows") || STARTS_WITH_CI(osFilename.c_str(), "/vsistdout")) ? "STREAM" : "FILE";

结合第一节的读取逻辑可以看出:FILE写出的是带ARROW1头尾签名与 footer 的可随机访问文件,STREAM写出的是连续 Record Batch 序列——这也解释了扩展名约定.arrow与.arrows的来源。

3.GEOMETRY_ENCODING— 几何编码

  • 取值:GEOARROW、WKB、WKT、GEOARROW_INTERLEAVED。
  • 默认值:GEOARROW。

官方文档特别强调了GDAL 3.9 的命名变化:

  • GDAL 3.9 起,GEOARROW使用 GeoArrow"struct" 结构体编码:点建模为带x、y子字段的 struct 字段,线建模为这种点的 list,依此类推。
  • 原版本中名为GEOARROW的编码在 3.9 被重命名为GEOARROW_INTERLEAVED:点使用(x,y)的FixedSizedList,线使用这种定长点列表的可变长 list,依此类推。

源码中选项到内部枚举的映射完全对应文档(ogrfeatherwriterlayer.cpp),且GEOARROW_STRUCT作为GEOARROW的别名接受。测试test_ogr_arrow_check_geoarrow_types用 PyArrow 逐类型验证了两种编码的底层 Arrow 类型(ogr_arrow.py),例如:

  • GEOARROW(struct 编码)的 Point →struct<x: double not null, y: double not null>
  • GEOARROW_INTERLEAVED的 Point →fixed_size_list<xy: double not null>[2]
  • Polygon 的 struct 编码 →list<rings: list<vertices: struct<x, y>>>

此外,写入几何列时驱动会在 schema 元数据(geo键)中记录schema_version、primary_column、每列的encoding、CRS(WKT2_2019 格式)与坐标纪元epoch,并在 footer 元数据(gdal:geo键)中额外写入bbox与gdal:geometry_type(ogrfeatherwriterlayer.cpp)。

4.BATCH_SIZE— 每批次最大行数

  • 取值:任意正整数。
  • 默认值:65536。

该值决定每个 Record Batch(写入批次)的最大行数。源码中若显式指定则覆盖默认值,且上限钳制为INT_MAX(ogrfeatherwriterlayer.cpp)。测试验证了批次数目与_ARROW_元数据域中NUM_RECORD_BATCHES、RECORD_BATCHES[N].NUM_ROWS的对应关系(ogr_arrow.py)。

5.GEOMETRY_NAME— 几何列名

  • 默认值:geometry。

用于指定写入的几何列名称,对应源码中CSLFetchNameValueDef(papszOptions, "GEOMETRY_NAME", "geometry")(ogrfeatherwriterlayer.cpp)。

6.FID— FID 列名

  • 默认值:不指定时不创建 FID 列。

官方文档特别提示了与 ogr2ogr 的联动:若使用 ogr2ogr 以 Arrow 驱动为目标驱动、且源图层带有命名 FID 列,该 FID 列名会被自动用来设置 Arrow 驱动的 FID 图层创建选项(除非用-lco FID=显式设为空名)。测试中通过FID=fid或FID=my_fid验证了 FID 列的创建与GetFIDColumn()行为(ogr_arrow.py)。

7.TIMESTAMP_WITH_OFFSET— 带时区偏移的时间戳

  • 取值:AUTO、YES、NO。
  • 默认值:AUTO。
  • 引入版本:3.13。

该选项决定 OGR 的 datetime 字段是否按 Arrow 官方的Timestamp With Offset 扩展规范(Apache Arrow Canonical Extensions 之一)写出为带偏移的时间戳字段。此类字段同时存储"UTC 时区下表达的时间戳"和"该 datetime 定义时区的 UTC 偏移量"两部分信息。三种模式的语义:

  • AUTO:只要 DateTime 字段报告混合时区标志(即OGRFieldDefn::GetTZFlag()返回OGR_TZFLAG_MIXED_TZ)就启用该扩展。
  • YES:强制启用——由于能自动设置混合时区标志的驱动很少,手动设为YES很有用。
  • NO:强制使用带 UTC 时区的 DateTime 字段。

源码在写入 schema 时按此逻辑为字段记录时区标志并生成arrow.timestamp_with_offset扩展名(ograrrowwriterlayer.hpp)。测试test_ogr_arrow_timestamp_with_offset构造了带+0345、-0745混合偏移的时间戳,验证写读往返后TZFLAG_MIXED_TZ与偏移值完整保留(ogr_arrow.py)。

六、安装方式

1. 随 GDAL 整体构建

Arrow 驱动由ogr/ogrsf_frmts/arrow/目录下的CMakeLists.txt负责构建,源码文件包括:

  • ogrfeatherdriver.cpp:驱动的 Open / Create / 元数据初始化
  • ogrfeatherdataset.cpp、ogrfeatherlayer.cpp:读取端数据集与图层
  • ogrfeatherwriterdataset.cpp、ogrfeatherwriterlayer.cpp:写入端
  • ogrfeatherdrivercore.cpp:Identify 与公共元数据
  • vsifilesystemregistrar.cpp:Arrow VSI 文件系统注册(仅当 Arrow ≥ 16.0 时编译,见 CMakeLists.txt)

驱动以PLUGIN_CAPABLE方式构建,并依赖Arrow::arrow_shared/arrow_static链接(CMakeLists.txt)。公共几何逻辑与 Parquet 驱动共享ogr/ogrsf_frmts/arrow_common/目录下的实现。

2. Conda-forge 插件包

官方文档提供的安装命令(作为libgdalconda-forge 包的插件):

conda install -c conda-forge libgdal-arrow-parquet

3. 独立插件编译(GDAL 3.10 起)

除了随整个 GDAL 构建(内置于 libgdal 或作为插件)之外,还可以仅将该驱动编译为插件,链接到已构建好的 libgdal。前提是:用于编译驱动的 GDAL 源码版本必须与所链接的 libgdal 版本一致。

官方文档示例(在 GDAL 源码树根目录下的build_arrow目录中执行):

cmake -S ../ogr/ogrsf_frmts/parquet -DCMAKE_PREFIX_PATH=/path/to/GDAL_installation_prefix -DArrow_DIR=/path/to/lib/cmake/Arrow cmake --build .

说明:示例命令以 GDAL 源码树内ogr/ogrsf_frmts/下的驱动源码目录为-S源,通过CMAKE_PREFIX_PATH指向 GDAL 安装前缀、Arrow_DIR指向 Arrow 的 CMake 配置目录。Arrow 驱动的CMakeLists.txt同样内置了独立插件构建支持(project(ogr_Arrow)+SetupStandalonePlugin.cmake,见 arrow/CMakeLists.txt)。

文档还提示了一个重要限制:此类插件在链接到不感知它的 libgdal 时,会在 GDAL 驱动初始化阶段被系统性加载,无法受益于延迟插件加载能力(RFC 96)。要启用延迟加载,需要 libgdal 自身以 CMake 变量OGR_REGISTER_DRIVER_ARROW_FOR_LATER_PLUGIN=ON构建。

七、Arrow VSI 文件系统(GDAL 3.10 起)

从 GDAL 3.10 与 Arrow 16.0 开始,任何 GDAL 虚拟文件系统都可以在只读上下文中,用于任何需要 URI 的 Arrow C++ 库位置,且不限于 OGR Arrow 驱动本身。启用方式(官方文档):

  1. 注册文件系统工厂:用arrow::fs::LoadFileSystemFactories()加载libgdal.so/dll(若 Arrow 驱动以插件库形式构建则加载ogr_Arrow.so/dll)。另外,如果 Arrow 驱动被完整加载(例如调用GetGDALDriverManager()->GetDriverByName("ARROW")->GetMetadata()),Arrow VSI 文件系统也会被自动注册。
  2. 使用gdalvsi://URI 前缀:在 GDAL 文件名可能自带的 vsi 前缀之外,再冠以该前缀。例如 GDAL 文件名/vsicurl/http://example.com对应的 Arrow URI 为gdalvsi:///vsicurl/http://example.com。

源码层面的注册实现在 vsifilesystemregistrar.cpp:通过ARROW_REGISTER_FILESYSTEM宏以gdalvsi作为 scheme 注册工厂,工厂回调剥离gdalvsi://前缀并返回基于 GDAL VSI 的VSIArrowFileSystem实现。驱动在RegisterOGRArrow()中还会读取OGR_ARROW_LOAD_FILE_SYSTEM_FACTORIES配置项(主要用于测试)来触发LoadFileSystemFactories()(ogrfeatherdriver.cpp)。

对应的自动化测试test_ogr_arrow_vsi_arrow_file_system在 Arrow ≥ 16 的环境下直接ogr.Open("gdalvsi://data/arrow/test.feather")验证该机制(ogr_arrow.py)。

八、实操示例

以下命令演示最常用的读写场景(基于 GDAL 命令行工具):

# 1. 将 Shapefile 转换为 Feather(File 格式,LZ4 压缩,GeoArrow struct 几何编码) ogr2ogr -f Arrow out.arrow in.shp \ -lco COMPRESSION=LZ4 \ -lco GEOMETRY_ENCODING=GEOARROW # 2. 写出流式 IPC 格式(输出到 stdout,自动判定为 STREAM 格式) ogr2ogr -f Arrow /vsistdout/ in.shp | cat > out.arrows # 3. 强制将文件按流式 IPC 格式打开(即使扩展名不是 .arrows) ogrinfo ARROW_IPC_STREAM:unknown_ext.bin -so -al # 4. 列出 Arrow 驱动的图层创建选项,查看当前环境实际可用的压缩方法 gdalinfo --format Arrow # 或查看驱动元数据 DS_LAYER_CREATIONOPTIONLIST

Python 端直接使用驱动 API:

from osgeo import gdal, ogr # 写入:单层限制 + FID 列 + 自定义批次大小 ds = gdal.GetDriverByName("Arrow").Create("out.feather", 0, 0, 0, gdal.GDT_Unknown) lyr = ds.CreateLayer("out", geom_type=ogr.wkbPoint, srs=srs, options=["GEOMETRY_ENCODING=GEOARROW", "FID=fid", "BATCH_SIZE=65536", "COMPRESSION=LZ4"]) # ... 创建字段与要素 ... ds = None # 关闭并完成文件写入 # 读取:强制按流式 IPC 打开 ds = gdal.OpenEx("ARROW_IPC_STREAM:/vsistdin/", gdal.OF_VECTOR) lyr = ds.GetLayer(0) for feat in lyr: print(feat.GetGeometryRef().ExportToIsoWkt())

九、相关资源

  • 官方格式文档:Feather File Format(Arrow Python 文档);GeoArrow 规范(GeoArrow 几何列标准,当前处于演进中)。
  • 关联驱动:Parquet 矢量驱动(与 Arrow 驱动共享arrow_common底层实现,测试中也互相复用检查逻辑)。
  • 驱动源码:ogr/ogrsf_frmts/arrow/(读写实现)、ogr/ogrsf_frmts/arrow_common/(公共 Arrow 桥接层)。
  • 测试套件:autotest/ogr/ogr_arrow.py(覆盖几何类型全矩阵、压缩、流式 stdin、VSI 文件系统、扩展类型、时间戳偏移等 1060 行用例)。
  • GIS
  • 遥感
  • 数据工程

【免费下载链接】gdal

GDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.

项目地址:https://gitcode.com/gh_mirrors/gd/gdal
点击查看免费下载

相关推荐

上一篇:Apache Beam 发布流程实战指南:从 Release Manager 视角的七阶段完整流程
下一篇:DLSS Swapper终极指南:三步快速优化游戏性能的免费神器

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询