在上学期课程设计有一道题就是读写 csv 文件,难倒很大一部分同学,最近开学的实验 0 又需要对文件进行读写,所以写这篇博客作总结。
因为只需要简易解析以达到保存数据的效果,所以也不需要表头。直接按数组索引为行,每个结构体元素为列进行存储。
数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
struct Birthday
{
int year, month, day;
};
struct Student_info
{
public:
std::string name;
std::string gender;
std::string number;
Birthday birthday;
std::string major;
int admission_score;
};
std::vector<Student> list;
|
在 C++ 通过 <sstream> 处理字符串流使得字符串解析变得更加容易,通过这一抽象接口读写转换字符串数据轻而易举。
csv 文件分析
csv 文件通过逗号分隔每一列,比如:
1
2
3
|
小东,男,234,20,3,4,123,312
小明,女,234,2023,2,2,计算机,213
小马,男,12,21,21,21,可,12
|
就是一个 csv 文件的基本内容。
所以只需要读取每一行,按逗号分隔每一数据即可进行解析,读入也是如此。
解析逗号
1
2
3
4
5
6
7
8
9
|
std::vector<std::string> division(const std::string &line)
{
std::vector<std::string> column;
std::string item;
std::stringstream ss(line);
while (std::getline(ss, item, ','))
column.emplace_back(item);
return column;
}
|
输入一行数字就能按逗号解析出每一个元素,将其以字符串的形式存储在数组中。
这里通过 stringstream 配合 getline 以指定分界符为 , 。
加载 csv 文件
通过 std::ifstream 数据结构读取 csv 文件,通过 getline 逐行读取文件。使用上面的 division 函数解析行,读入对于结构体。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
std::vector<Student> load_from_csv(std::string path)
{
std::ifstream in(path, std::fstream::out | std::ifstream::in);
if (!in)
return std::vector<Student>{};
std::vector<Student> data;
std::string line;
while (std::getline(in, line))
{
if (line.empty())
continue;
std::vector<std::string> f = division(line);
Student_info stu;
stu.name = f[0];
stu.gender = f[1];
stu.number = f[2];
stu.birthday.year = std::stoi(f[3]);
stu.birthday.month = std::stoi(f[4]);
stu.birthday.day = std::stoi(f[5]);
stu.major = f[6];
stu.admission_score = std::stoi(f[7]);
Student in(stu);
data.emplace_back(in);
}
return data;
}
|
写入 csv 文件
写入 csv 文件相对简单,只需要通过 ofstream 覆盖写入即可。
1
2
3
4
5
6
7
8
9
10
11
|
void write_to_csv(std::string path)
{
std::ofstream out(path);
for (auto &s : list)
{
out << s.info.name << "," << s.info.gender << "," << s.info.number << "," << s.info.birthday.year << ","
<< s.info.birthday.month << "," << s.info.birthday.day << "," << s.info.major << ","
<< s.info.admission_score << "\n";
}
}
|