第4章:数据存储格式——CSV、JSON、Parquet、HDF5、ROS Bag、自定义二进制格式
做数据回放和场景复现,说白了就是跟各种文件格式打交道。我这些年折腾下来,发现选对格式,能让你少掉一半头发。今天咱们就把这六种主流格式掰开揉碎聊一聊。
4.1 CSV——最朴实的通用格式
CSV 是我用得最多的格式,没有之一。为什么?因为它简单到极致——任何文本编辑器都能打开,Excel 直接双击就能看。
但别被它的外表骗了。我在项目中遇到过一个大坑:某次回放自动驾驶的 CAN 总线数据,CSV 里存了时间戳和车速。结果回放时发现时间戳精度不够,毫秒级的数据被四舍五入成了秒。嗯,这里要注意——CSV 天生不带数据类型信息,全靠你解析时自己定义。
# 一个典型的 CSV 回放场景
timestamp,speed,steering_angle
1630000000.123,35.2,0.15
1630000000.456,35.8,0.18
4.2 JSON——结构化数据的首选
JSON 的好处是自带层级结构。你想想看,一个传感器数据包,里面可能包含多个子字段——位置、姿态、置信度。用 CSV 你得拆成好几列,用 JSON 直接嵌套就完事了。
我个人习惯在调试阶段用 JSON。因为它可读性好,出错了看一眼就知道问题在哪。但要注意,JSON 的解析开销比 CSV 大不少。我曾经在嵌入式设备上跑 JSON 解析,CPU 直接飙到 80%。
{
"timestamp": 1630000000.123,
"sensor": "lidar",
"data": {
"points": 128000,
"range": 100.0,
"resolution": 0.1
}
}
4.3 Parquet——列式存储的王者
Parquet 是这两年我越来越依赖的格式。它采用列式存储,什么意思呢?就是同一列的数据挨在一起存。这样做的好处是——你查询某个字段时,只需要读那一列的数据,IO 开销小得惊人。
我在做自动驾驶场景回放时,经常要按时间戳范围筛选数据。Parquet 的谓词下推功能可以直接在文件层面过滤,不用把整个文件读到内存。速度比 CSV 快 10 倍以上。
| 特性 | CSV | Parquet |
|---|---|---|
| 压缩率 | 低(文本存储) | 高(列式压缩) |
| 查询性能 | 全表扫描 | 列裁剪 + 谓词下推 |
| Schema 支持 | 无 | 强类型 |
4.4 HDF5——科学计算的瑞士军刀
HDF5 这玩意儿,说白了就是给大数据准备的容器。它支持多维数组、分块存储、并行 IO。我在做气象数据回放时用过它——一个文件里存了 10 年的温度场数据,按时间、高度、经纬度分块存储,查询任意切片都很快。
但 HDF5 有个问题:版本兼容性。我记得有一次升级了 HDF5 库,结果之前写的文件打不开了。嗯,这里要提醒你——生产环境里,HDF5 的版本一定要锁定。
# HDF5 的典型结构
/ (根组)
├── /sensor_data (组)
│ ├── /sensor_data/lidar (数据集)
│ └── /sensor_data/camera (数据集)
├── /metadata (组)
│ └── /metadata/calibration (数据集)
4.5 ROS Bag——机器人领域的标配
做机器人或自动驾驶的,没人不知道 ROS Bag。它本质上是一个消息录制器——把 ROS 话题上的消息按时间顺序存下来。回放时就像时光倒流一样,所有话题按原来的时间戳重新发布。
我遇到过最头疼的问题是 Bag 文件太大。一次路测 8 小时,录了 500GB 的数据。后来我学会了用 rosbag compress 压缩,能省 60% 的空间。
rosbag filter 可以按话题或时间范围裁剪 Bag 文件,只保留你关心的数据。
4.6 自定义二进制格式——终极性能方案
有时候,现成的格式都不够用。比如你要在 FPGA 上直接回放数据,或者需要极致的 IO 性能。这时候就得自己定义二进制格式。
我做过一个项目:回放激光雷达的点云数据,每秒 30 帧,每帧 128000 个点。用 ROS Bag 回放,CPU 占用 40%。换成自定义二进制格式,直接内存映射文件,CPU 占用降到 5%。
// 自定义二进制格式示例
struct PointCloudFrame {
uint64_t timestamp; // 8 字节
uint32_t point_count; // 4 字节
float points[]; // 每个点 12 字节 (x, y, z)
};
知识体系总览
下面这张图,是我梳理的六种格式的选型逻辑。你可以把它当作决策地图。
说白了,没有银弹。每种格式都有自己的脾气。我的经验是——先用 CSV 或 JSON 快速验证思路,数据量上来了再切 Parquet 或 HDF5。如果是机器人项目,ROS Bag 是绕不开的。至于自定义二进制格式,那是最后的大招,不到万不得已别轻易用。
记住一点:格式只是载体,数据本身才是核心。选格式的时候,多想想你的使用场景——是离线分析还是实时回放?是单机处理还是分布式?想清楚了,选择自然就出来了。