如何在C++中使用Google Protocol Buffer将CSV文件转换为二进制文件
C++ 基于Google Protobuf实现CSV转二进制文件操作指南
1. 先解决Protobuf库导入问题(环境配置)
1.1 库安装
- Linux:直接执行包管理命令
sudo apt install libprotobuf-dev protobuf-compiler - Windows/Mac:可以下载Protobuf官方源码编译,编译完成后将生成的
include目录、lib目录,以及protoc可执行文件路径加入系统环境变量
1.2 项目引入配置
如果你用CMake构建项目,直接在CMakeLists.txt中加入如下配置即可自动关联Protobuf库:
cmake_minimum_required(VERSION 3.10) project(csv_to_pb) find_package(Protobuf REQUIRED) include_directories(${PROTOBUF_INCLUDE_DIRS}) # 此处替换为你自己的源码和生成的protobuf源码文件 add_executable(csv_to_bin main.cpp your_proto_file.pb.cc) target_link_libraries(csv_to_bin ${PROTOBUF_LIBRARIES})
如果你用Visual Studio手动配置:
- 项目属性→C/C++→常规→附加包含目录:添加Protobuf的
include路径 - 项目属性→链接器→常规→附加库目录:添加Protobuf的
lib路径 - 项目属性→链接器→输入→附加依赖项:添加
libprotobuf.lib(Release)/libprotobufd.lib(Debug)
2. 定义匹配CSV结构的Protobuf消息
假设你的CSV文件结构为:id,姓名,年龄,分数,首先创建后缀为.proto的定义文件,示例如下:
syntax = "proto3"; package data; message SingleRow { int32 id = 1; string name = 2; int32 age = 3; float score = 4; } message CsvAllData { repeated SingleRow rows = 1; }
定义完成后执行protoc命令生成C++代码:protoc --cpp_out=./ 你的proto文件名.proto
执行后会生成两个文件:你的proto文件名.pb.h和你的proto文件名.pb.cc,后续要加入你的项目中一起编译。
3. 编写转换逻辑代码
完整示例代码如下,无需引入第三方CSV解析库,适配新手使用:
#include <iostream> #include <fstream> #include <string> #include <vector> #include <sstream> // 引入生成的protobuf头文件 #include "你的proto文件名.pb.h" // 简单CSV行拆分函数,按逗号分割 std::vector<std::string> split(const std::string& s, char delimiter) { std::vector<std::string> tokens; std::string token; std::istringstream tokenStream(s); while (std::getline(tokenStream, token, delimiter)) { tokens.push_back(token); } return tokens; } int main() { // 初始化Protobuf GOOGLE_PROTOBUF_VERIFY_VERSION; data::CsvAllData all_data; std::ifstream csv_file("你的输入文件.csv"); std::string line; // 跳过CSV表头(如果你的CSV没有表头可以删掉这一行) std::getline(csv_file, line); // 逐行读取CSV while (std::getline(csv_file, line)) { std::vector<std::string> cols = split(line, ','); if (cols.size() != 4) { // 字段数量要和你定义的SingleRow字段数匹配 std::cerr << "跳过格式错误行:" << line << std::endl; continue; } // 填充Protobuf消息 data::SingleRow* row = all_data.add_rows(); row->set_id(std::stoi(cols[0])); row->set_name(cols[1]); row->set_age(std::stoi(cols[2])); row->set_score(std::stof(cols[3])); } // 序列化写入二进制文件 std::ofstream bin_file("输出的二进制文件.bin", std::ios::out | std::ios::binary); if (!all_data.SerializeToOstream(&bin_file)) { std::cerr << "写入二进制文件失败" << std::endl; return -1; } // 释放Protobuf资源 google::protobuf::ShutdownProtobufLibrary(); return 0; }
4. 编译运行注意事项
- 代码中的字段数量、类型要和你自己的CSV结构、proto定义完全匹配,避免转换错误
- 如果用g++直接编译,命令参考:
g++ main.cpp 你的proto文件名.pb.cc -o csv2bin -lprotobuf - 生成的二进制文件可以通过Protobuf的
ParseFromIstream接口直接读取反序列化,无需再做格式解析
内容的提问来源于stack exchange,提问作者SHREESHA ATHREYAS M
相关产品推荐
相关产品推荐

