在 C++ 中读取 CSV 文件
本文将说明几种如何在 C++ 中读取 CSV 文件的方法。
使用 std::getline
和 std::istringstream
读取 C++ 中的 CSV 文件
CSV 文件通常称为文本文件格式,其中的值在每行中用逗号分隔。行称为数据记录,每条记录通常包含多个字段,以逗号分隔。CSV 格式主要用于存储表格数据,因此每个记录中包含相等数量的逗号分隔符。但是请注意,由于实际上有多种实现,因此可能会发现例如以逗号分隔的字段之间有空格,或者字段之间可能没有空格等。在以下示例中,我们假定之间没有空格田野。因此,逗号之间的每个字符都被视为一个数据单元。
首先,我们需要读取文件内容并将其存储在 std::string
对象中。readFileIntoString
函数利用 std::ostringstream
和 rdbuf
读取文件,并将 string
值返回给调用方函数。一旦上一步成功完成,我们就可以从字符串
对象构造一个 std::istringstream
,并在每行上进行迭代。在此迭代中,我们放置了另一个循环以提取一行中的每个字段,并将它们存储在 std::vector
中。在每行迭代结束时,我们将 vector
存储在 std::map
中,并清除 vector
进行下一个循环。请注意,std::map
可以替换为向量的向量或对特定情况最佳的任何其他自定义数据结构。
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <map>
using std::cout; using std::cerr;
using std::endl; using std::string;
using std::ifstream; using std::ostringstream;
using std::istringstream;
string readFileIntoString(const string& path) {
auto ss = ostringstream{};
ifstream input_file(path);
if (!input_file.is_open()) {
cerr << "Could not open the file - '"
<< path << "'" << endl;
exit(EXIT_FAILURE);
}
ss << input_file.rdbuf();
return ss.str();
}
int main()
{
string filename("grades.csv");
string file_contents;
std::map<int, std::vector<string>> csv_contents;
char delimiter = ',';
file_contents = readFileIntoString(filename);
istringstream sstream(file_contents);
std::vector<string> items;
string record;
int counter = 0;
while (std::getline(sstream, record)) {
istringstream line(record);
while (std::getline(line, record, delimiter)) {
items.push_back(record);
}
csv_contents[counter] = items;
items.clear();
counter += 1;
}
exit(EXIT_SUCCESS);
}
外部的 while
循环使用默认定界符(换行符)调用 getline
,而内部的循环将逗号字符指定为第三个参数。与前面的示例代码相反,下一个示例代码实现了一种解决方案,以处理字段中的尾随空格并解析数据单元,然后再将其存储在向量
中。因此,在调用 push_back
之前,我们在内部的 while
循环中添加了 erase-remove
习惯用法。因为我们将 isspace
函数对象用作 remove_if
参数,所以它将处理任何空格字符,例如空格、制表符、回车符和其他字符。
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <map>
using std::cout; using std::cerr;
using std::endl; using std::string;
using std::ifstream; using std::ostringstream;
using std::istringstream;
string readFileIntoString(const string& path) {
auto ss = ostringstream{};
ifstream input_file(path);
if (!input_file.is_open()) {
cerr << "Could not open the file - '"
<< path << "'" << endl;
exit(EXIT_FAILURE);
}
ss << input_file.rdbuf();
return ss.str();
}
int main()
{
string filename("grades.csv");
string file_contents;
std::map<int, std::vector<string>> csv_contents;
char delimiter = ',';
file_contents = readFileIntoString(filename);
istringstream sstream(file_contents);
std::vector<string> items;
string record;
int counter = 0;
while (std::getline(sstream, record)) {
istringstream line(record);
while (std::getline(line, record, delimiter)) {
record.erase(std::remove_if(record.begin(), record.end(), isspace), record.end());
items.push_back(record);
}
csv_contents[counter] = items;
items.clear();
counter += 1;
}
exit(EXIT_SUCCESS);
}
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn