读取大.csv文件?

Reading large .csv file?

本文关键字:文件 csv 读取      更新时间:2023-10-16

我正在尝试读取一个大约 50 万行的.csv文件。在下面的代码中,我一次读取每一行,将其解析为名为NinjaInfo_t的预定义结构,然后将其推送到列表中。阅读此文件的整个过程花了我 1 分钟多的时间。有没有另一种方法可以更快?这也是一个家庭作业,所以我不能使用任何支持读取csv文件的库,我必须使用链表来存储数据。

ifstream is("data.csv",ifstream::binary);
is.seekg(0, ios_base::end);
size_t size = is.tellg();
is.seekg(0, ios_base::beg);
char* buffer = new char[size];
is.read(buffer, size);
stringstream ss;
ss.str(buffer);
// skip the file line in data.csv
string data;
getline(ss, data);
while (getline(ss, data)) {
NinjaInfo_t newData;
stringstream dataStream;
dataStream.str(data);
string tmp;
string timestamp;
string id;
string longtitude, latitude;
getline(dataStream, tmp, ',');
getline(dataStream, timestamp, ',');
getline(dataStream, id, ',');
getline(dataStream, longtitude, ',');
getline(dataStream, latitude, ',');
getline(dataStream, tmp);
istringstream(longtitude) >> newData.longitude;
istringstream(latitude) >> newData.latitude;
while (id.length() < 4) {
id = '0' + id;
}
istringstream(id) >> newData.id;
stringstream ss;
struct tm _tm = {};
string t = timestamp;
ss.str(t);
ss >> std::get_time(&_tm, "%d/%m/%Y %H:%M:%S");
_tm.tm_isdst = -1;
time_t time = std::mktime(&_tm);
newData.timestamp = time;
db.push_back(newData); //DB IS A LINKED LIST.

附言:很抱歉英语:P不好。

性能不佳有两个主要原因:

  • 通过在每次迭代(即构造函数/初始化/析构函数)创建一次性istringstream,而不仅仅是进行转换(例如使用std::stoi()等),会产生大量开销。
  • 您将每条记录push_back()到一个db向量(我假设)。 但随着其规模的增长,它需要频繁地重新分配和移动它所包含的数据。 您可以在开始时reserve()预期的空间,只是为了减少此内存管理开销。

注意 1:目前尚不清楚,如果像您那样立即读取文件会带来显着的性能提升,因为无论如何文件流都会被缓冲。

注意 2:请注意,您的 CSV 处理与 RFC 4180 不完全一致,RFC 4180 允许在引号之间括住数据中的换行符。