我需要读取许多大的 CSV 文件以在 C++ 中进行处理(范围从几 MB 到数百 MB)
首先,我使用 fstream 打开,使用 getline 读取每一行并使用以下函数
分割每一行”
template < class ContainerT >
void split(ContainerT& tokens, const std::string& str, const std::string& delimiters = " ", bool trimEmpty = false)
{
std::string::size_type pos, lastPos = 0, length = str.length();
using value_type = typename ContainerT::value_type;
using size_type = typename ContainerT::size_type;
while (lastPos < length + 1)
{
pos = str.find_first_of(delimiters, lastPos);
if (pos == std::string::npos)
{
pos = length;
}
if (pos != lastPos || !trimEmpty)
tokens.push_back(value_type(str.data() + lastPos,
(size_type)pos - lastPos));
lastPos = pos + 1;
}
}
我尝试了 boost::split、boost::tokenizer 和 boost::sprint 并发现上面给出了
迄今为止最好的表现。
之后,我考虑将整个文件读入内存进行处理,而不是保持文件打开,
我使用以下函数通过以下函数读取整个文件:
void ReadinFile(string const& filename, stringstream& result)
{
ifstream ifs(filename, ios::binary | ios::ate);
ifstream::pos_type pos = ifs.tellg();
//result.resize(pos);
char * buf = new char[pos];
ifs.seekg(0, ios::beg);
ifs.read(buf, pos);
result.write(buf,pos);
delete[]buf;
}
这两个函数都是从网络上的某个地方复制的。然而,我发现
保持文件打开或读入在性能上没有太大差异
整个文件。
性能捕获如下:
Process 2100 files with boost::split (without read in whole file) 832 sec
Process 2100 files with custom split (without read in whole file) 311 sec
Process 2100 files with custom split (read in whole file) 342 sec
下面请找到一种类型文件的示例内容,我有 6 种类型需要处理。但一切都是相似的。
a1,1,1,3.5,5,1,1,1,0,0,6,0,155,21,142,22,49,1,9,1,0,0,0,0,0,0,0
a1,10,2,5,5,1,1,2,0,0,12,0,50,18,106,33,100,29,45,9,8,0,1,1,0,0,0
a1,19,3,5,5,1,1,3,0,0,18,0,12,12,52,40,82,49,63,41,23,16,8,2,0,0,0
a1,28,4,5.5,5,1,1,4,0,0,24,0,2,3,17,16,53,53,63,62,43,44,18,22,4,0,4
a1,37,5,3,5,1,1,5,0,0,6,0,157,22,129,18,57,11,6,0,0,0,0,0,0,0,0
a1,46,6,4.5,5,1,1,6,0,0,12,0,41,19,121,31,90,34,37,15,6,4,0,2,0,0,0
a1,55,7,5.5,5,1,1,7,0,0,18,0,10,9,52,36,86,43,67,38,31,15,5,7,1,0,1
a1,64,8,5.5,5,1,1,8,0,0,24,0,0,3,18,23,44,55,72,57,55,43,8,19,1,2,3
a1,73,9,3.5,5,1,1,9,1,0,6,0,149,17,145,21,51,8,8,1,0,0,0,0,0,0,0
a1,82,10,4.5,5,1,1,10,1,0,12,0,47,17,115,35,96,36,32,10,8,3,1,0,0,0,0
我的问题是:
1 为什么读入整个文件会比不读入整个文件表现更差?
2 还有其他更好的字符串分割函数吗?
3 ReadinFile函数需要读取到缓冲区然后写入字符串流来处理,
有什么方法可以避免这种情况吗?即直接进入 stringstream
4 我需要使用 getline 来解析每一行(使用 \n)并使用 split 来标记每一行,
有类似 getline for string 的函数吗?例如获取行_str?以便
我可以直接读入字符串
5 如何将整个文件读入字符串,然后用“\n”将整个字符串拆分为向量,然后用“,”将向量中的每个字符串拆分来处理?这样效果会更好吗? string 的限制(最大大小)是多少?
6 或者我应该定义一个像这样的结构(基于格式)
struct MyStruct {
string Item1;
int It2_3[2];
float It4;
int ItRemain[23];
};
并直接读入向量?这个怎么做 ?
多谢。
Regds
林志峰