直接用 parquet-cpp 会编译失败或链接报错,因其自2019年起已并入Arrow项目,头文件、命名空间和构建方式全面变更;应改用Arrow的Parquet模块,包含对应头文件、链接arrow和arrow_parquet库,并确保运行时库路径正确。

为什么直接用 parquet-cpp 会编译失败或链接报错
Apache 官方已将 Parquet C++ 实现完全并入 Arrow 项目,parquet-cpp 仓库自 2019 年起归档,头文件路径、命名空间、构建方式全部变更。你现在看到的旧教程里写的 #include "parquet/reader.h" 或链接 -lparquet,大概率会触发 fatal error: parquet/reader.h: No such file or directory 或未定义引用错误。
正确做法是统一使用 Arrow 的 Parquet 模块:
- 头文件全走
#include <arrow></arrow>和#include <arrow></arrow>,Parquet 相关接口在<arrow></arrow> - CMake 中必须 find_package(Arrow REQUIRED) 且 link
arrow+arrow_parquet(不是parquet) - 运行时需确保
libarrow_parquet.so(Linux)或arrow_parquet.dll(Windows)在 LD_LIBRARY_PATH / PATH 中
如何用 parquet::ParquetFileReader 同步读取单个文件
Arrow 的 Parquet 读取分两步:先打开文件获取元数据和 schema,再按行组(RowGroup)或整列拉取数据。不推荐一次性读全——内存爆炸风险高,且失去列裁剪优势。
基础流程示例:
立即学习“C++免费学习笔记(深入)”;
#include <arrow/parquet/api.h>
#include <arrow/io/file.h>
std::shared_ptr<arrow::io::ReadableFile> infile;
arrow::io::ReadableFile::Open("data.parquet", &infile).AbortNotOk();
std::unique_ptr<parquet::ParquetFileReader> reader =
parquet::ParquetFileReader::Open(infile);
// 获取 schema(Arrow 格式)
std::shared_ptr<arrow::Schema> schema = reader->metadata()->schema();
// 读第 0 个 RowGroup(可循环读多个)
std::shared_ptr<arrow::Table> table;
reader->ReadRowGroup(0, &table).AbortNotOk(); // 注意:返回的是 Table,非原始 Parquet 数据
关键点:
-
ReadRowGroup()返回arrow::Table,列已自动解码为 Arrow 原生类型(如arrow::Int32Array),无需手动 cast - 若只需某几列,用
ReadRowGroup({0, 2, 4})传列索引列表,避免加载无关列 - 不调
ReadTable()—— 它会读全部 RowGroup,内存占用不可控
遇到 ArrowNotImplementedError: Dictionary decoding not supported for type 怎么办
这是 Arrow 5.x+ 默认禁用字典解码导致的常见报错,尤其出现在用 Python(pyarrow)写入、C++ 读取的混合场景中。Parquet 文件若含字典编码列(string / enum 等高频值),Arrow C++ 默认不处理该编码格式。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
解决方法是在打开 reader 时显式启用字典支持:
parquet::ReaderProperties props;
props.set_use_dictionary(true); // 关键
std::unique_ptr<parquet::ParquetFileReader> reader =
parquet::ParquetFileReader::Open(infile, props);
其他相关配置:
-
props.set_pre_buffer(true):预读底层页,提升小文件随机访问性能 -
props.set_threads(4):开启多线程解码(仅对大 RowGroup 有效) - 若确定无字典列,设
set_use_dictionary(false)可略降初始化开销
如何把 arrow::Table 转成原生 C++ 结构(如 std::vector<int32_t>)
Arrow 的 Table 是零拷贝视图,直接转 std::vector 需显式拷贝。别试图 reinterpret_cast —— Arrow 内存布局含 offset / validity bitmap,结构不兼容。
安全提取整列 int32 示例:
std::shared_ptr<arrow::ChunkedArray> col = table->column(0);
std::shared_ptr<arrow::Int32Array> arr =
std::static_pointer_cast<arrow::Int32Array>(col->chunk(0));
std::vector<int32_t> data(arr->length());
arr->CopyUnslicedData(data.data()); // 自动跳过 null 值?不,这行只拷贝有效数据(含 null 占位)
更稳妥的做法(处理 null):
- 用
arr->raw_values()+arr->null_count() > 0判断是否含 null - 若需过滤 null,遍历
arr->IsValid(i)手动 push_back - 字符串列务必用
arr->GetString(i),不能直接取 raw_values —— Arrow string 是 offset-based
真正麻烦的是嵌套类型(struct / list)和时区感知 timestamp —— 这些得逐层 unpack,没通用捷径。


















