CSV文件是常用的轻量级数据存储格式,很多小型应用会用它替代数据库存储结构化数据。用C++实现CSV文件的检索功能,不需要依赖第三方库,通过标准库就能完成核心逻辑。

核心实现思路
实现CSV检索功能主要分为四个步骤:读取CSV文件内容、解析每行数据拆分字段、根据检索条件匹配数据、输出匹配结果。首先需要明确CSV文件的结构,假设我们的CSV文件第一行是表头,后续每行是一条数据记录,字段之间用逗号分隔,且字段内容不包含逗号和换行符,简化解析逻辑。
完整实现代码
1. 头文件与数据结构定义
首先定义存储CSV数据的结构,用vector存储所有行,每行用vector存储各个字段:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <stdexcept>
// 存储CSV单条记录的结构
struct CSVRecord {
std::vector<std::string> fields;
};
// 存储整个CSV数据的结构
struct CSVDatabase {
std::vector<std::string> headers; // 表头
std::vector<CSVRecord> records; // 所有记录
};
2. CSV文件读取与解析函数
实现读取CSV文件并解析为CSVDatabase结构的函数:
// 读取CSV文件,返回解析后的数据库结构
CSVDatabase loadCSV(const std::string& filePath) {
CSVDatabase db;
std::ifstream file(filePath);
if (!file.is_open()) {
throw std::runtime_error("无法打开CSV文件: " + filePath);
}
std::string line;
// 读取表头
if (std::getline(file, line)) {
std::stringstream ss(line);
std::string header;
while (std::getline(ss, header, ',')) {
db.headers.push_back(header);
}
}
// 读取数据行
while (std::getline(file, line)) {
if (line.empty()) continue; // 跳过空行
CSVRecord record;
std::stringstream ss(line);
std::string field;
while (std::getline(ss, field, ',')) {
record.fields.push_back(field);
}
// 确保字段数量和表头一致,不足补空
while (record.fields.size() < db.headers.size()) {
record.fields.push_back("");
}
db.records.push_back(record);
}
file.close();
return db;
}
3. 检索功能实现
实现按指定字段名和关键词检索的函数,支持精确匹配:
// 检索CSV数据,返回匹配的记录索引
std::vector<int> searchCSV(const CSVDatabase& db, const std::string& fieldName, const std::string& keyword) {
std::vector<int> resultIndices;
// 先找到字段名对应的索引
int fieldIndex = -1;
for (size_t i = 0; i < db.headers.size(); ++i) {
if (db.headers[i] == fieldName) {
fieldIndex = i;
break;
}
}
if (fieldIndex == -1) {
std::cout << "未找到字段: " << fieldName << std::endl;
return resultIndices;
}
// 遍历所有记录匹配关键词
for (size_t i = 0; i < db.records.size(); ++i) {
const auto& record = db.records[i];
if (fieldIndex < record.fields.size() && record.fields[fieldIndex] == keyword) {
resultIndices.push_back(i);
}
}
return resultIndices;
}
4. 结果输出与测试
实现输出检索结果的函数,并编写测试代码:
// 输出检索结果
void printSearchResult(const CSVDatabase& db, const std::vector<int>& indices) {
if (indices.empty()) {
std::cout << "未找到匹配的记录" << std::endl;
return;
}
// 输出表头
for (size_t i = 0; i < db.headers.size(); ++i) {
std::cout << db.headers[i];
if (i != db.headers.size() - 1) {
std::cout << ",";
}
}
std::cout << std::endl;
// 输出匹配的记录
for (int idx : indices) {
const auto& record = db.records[idx];
for (size_t i = 0; i < record.fields.size(); ++i) {
std::cout << record.fields[i];
if (i != record.fields.size() - 1) {
std::cout << ",";
}
}
std::cout << std::endl;
}
}
int main() {
try {
// 加载CSV文件,假设文件名为test.csv,内容如下:
// name,age,city
// 张三,25,北京
// 李四,30,上海
// 王五,25,广州
CSVDatabase db = loadCSV("test.csv");
// 检索年龄为25的记录
std::vector<int> results = searchCSV(db, "age", "25");
std::cout << "检索年龄为25的结果:" << std::endl;
printSearchResult(db, results);
} catch (const std::exception& e) {
std::cerr << "错误: " << e.what() << std::endl;
}
return 0;
}
功能扩展方向
上述代码实现了基础的精确匹配检索,你可以根据需求扩展功能:
- 支持模糊匹配,比如用
std::string::find判断是否包含关键词 - 支持多条件检索,比如同时匹配年龄和城市两个字段
- 处理包含逗号的字段,比如字段用双引号包裹的情况,解析时先判断引号
- 支持按字段排序后输出结果
注意事项
实际使用中需要注意CSV文件的编码问题,默认用标准库读取的是本地编码,如果有中文乱码需要处理编码转换。另外如果CSV文件体积较大,一次性加载到内存可能占用过多资源,可以改为逐行读取匹配,减少内存占用。