С++ Быстрое чтение из текстового файла

Осваиваю с++ после c#. Пишу программу для обработки словарей для на с++.

Хочу считывать файл в память в виде массива строк или вектора со строками

столкнулся с проблемой выбора варианта считывания текстового файла с диска. Диск SSD. файл размером 136 МБ считывается вот таким способом:

ifstream file("rockyou.txt");

file.seekg(0, ios_base::end);

size_t size = file.tellg();

file.seekg(0, ios_base::beg);

string buffer(size, ' ');

file.read(&buffer[0], size);

за ~700 мс. Быстро, но в буфере получаем массив символов и для построчной дальнейшей обработки это не подходит. Если считывать так:

   list<string> stringList;

   if (file.is_open())
    {
        while (!file.eof())
        {
            getline(file, line);
            stringList.push_back(line);
        }
        file.close();
    }

То считывается в лист строк за 7800 мс. Обрабатывать строки можно, но скорость низкая. К примеру C# в таком варианте даже с проверкой на условие тот же словарь обрабатывает за 1380мс:

 using(StreamReader streamReader = File.OpenText(inputDict))
    {
        string s = String.Empty;
        while ((s = streamReader.ReadLine()) != null)
        {
            
            if(s.Length>7 && s.Length < 30 && !(s.IndexOf(' ') >= 0))
            {
                count++; 
            }
        }    
        
    }

Хочется именно разобраться с решением задачи в среде С++ больше с образовательной целью.


Ответы (2 шт):

Автор решения: Deim

Наиболее быстрый способ открытия файла оказался следующим (~300мс):

std::ifstream infile;
infile.open("D:\\dict\\rockyou.txt", std::ios::binary); // откроем файл как бинарный
infile.seekg(0, std::ios::end);
size_t file_size_in_byte = infile.tellg();
std::vector<char> data; // будем использовать для хранения текста
data.resize(file_size_in_byte);
infile.seekg(0, std::ios::beg);
infile.read(&data[0], file_size_in_byte);

string test(data.begin(), data.end()); //переведём в одну строку

Как упоминали в комментариях выше в полученной строке все строки из исходного файла разделены '\n'. Пока не нашёл способ закинуть все слова в массив или вектор. При попытке в цикле запихнуть слова в вектор получаю что объем памяти увеличивается до 2 и более Гб. При весе исходного файла в 136 мб.

string tmp;
vector<string> stringList;
for (char ch : data)
{
    if (ch != '\n')
    {
        tmp += ch;
    }
    else
    {            
        stringList.push_back(tmp);            
        tmp.clear();            
    }
}
→ Ссылка
Автор решения: MBo

Псевдокод для разбора массива данных по строкам (на случай, если стандартные методы с cin и пр. не хочется применять):

string tmp;
int returnpos = 0;
vector<string> stringList;
for (int i = 0; i< datalength; i++)
{
    if (data[i] == '\n')
    {
        make string tmp with length = i - returnpos
        movememory(&data[returnpos + 1], &tmp[0], i - returnpos);
        stringList.push_back(tmp);            
        returnpos = i;
    }
}
→ Ссылка