Мне нужно прочитать много больших CSV-файлов для обработки в C ++ (от нескольких МБ до сотен МБ)
Сначала я открываю с помощью 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 должна читать в буфер, а затем записывать в поток строк для обработки,
любой способ избежать этого? то есть непосредственно в поток строк
4 Мне нужно использовать getline для разбора каждой строки (с \ n) и использовать split для токенизации каждой строки,
любая функция похожа на getline для строки? например getline_str? чтобы
Я могу читать в строку непосредственно
5 Как насчет прочитать весь файл в строку, а затем разбить всю строку на вектор с помощью '\ n', а затем разбить каждую строку в векторе с помощью ',' для обработки? Будет ли это работать лучше? И какой предел (максимальный размер) строки?
6 Или я должен определить такую структуру (в зависимости от формата)
struct MyStruct {
string Item1;
int It2_3[2];
float It4;
int ItRemain[23];
};
а читать прямо в вектор? Как это сделать?
Большое спасибо.
Regds
LAM Chi-fung