Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/25: Рейтинг темы: голосов - 25, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 24.04.2019
Сообщений: 6

Быстрое чтение из файла

24.02.2020, 14:12. Показов 4887. Ответов 7
Метки c++ (Все метки)

Студворк — интернет-сервис помощи студентам
Не подскажите, как быстро считать данные из файла? Вот пример файла:
4
3 qwe
10 sadv
2 sadv
1 blaaaa
В первой строке идёт количество таких пар. Желательно как ещё можно разбить этот ввод на массив пар. Если использовать getline, то выполняется очень долго, так как количество таких пар может достигать 10^9. Возможно ли это сделать как-то побыстрее?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
24.02.2020, 14:12
Ответы с готовыми решениями:

Быстрое чтение файла
Здраствуйте. Я пишу программу, которая читает файлы порядка от нескольких килобайтов до максимум 3 Мб. Посоветуйте пожалуйста, какие...

Быстрое чтение массива из файла
Добрый день, появился вроде бы не сложный вопрос, у меня есть динамический массив данных double ** data; // пусть 200x500 //я его...

Быстрое чтение и запись файлов
Вопрос такой: имеется файл input.txt следующего вида: 5 12 6 7 44 2 1 2 3 4 5 2 343 634 54 1 123 2 345 56 56 11111 2222...

7
Параллельный Кот
 Аватар для valen10
1905 / 827 / 350
Регистрация: 25.03.2016
Сообщений: 2,045
24.02.2020, 14:20
Потоковый ввод чем не устроил?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct Rec {
    int x;
    string text;
};
 
// ...
 
ifstream fin("in.txt");
unsigned n;
fin >> n;
Rec* a = new Rec [n];
 
for (unsigned i = 0; i < n; ++i) {
    fin >> a[i].x >> a[i].text;
}
Вот только хватит ли памяти для размещения такого количества данных? Напишите лучше, какую задачу решаете. Возможно, нет необходимости все считывать в массив.
0
0 / 0 / 0
Регистрация: 24.04.2019
Сообщений: 6
24.02.2020, 15:15  [ТС]
Пирамидальная сортировка. Нужно отсортировать данные по ключу

Добавлено через 16 минут
Потоковый ввод работает медленно. Программа не должна работать более одной минуты, сказано в условии задачи, а потоковый ввод на 10^8 работает уже больше минуты
0
Параллельный Кот
 Аватар для valen10
1905 / 827 / 350
Регистрация: 25.03.2016
Сообщений: 2,045
24.02.2020, 19:50

Не по теме:

Дело было вечером, делать было нечего...


Цитата Сообщение от roger21 Посмотреть сообщение
Потоковый ввод работает медленно. Программа не должна работать более одной минуты
Стоит учесть, что за это время необходимо еще выполнить сортировку и записать всё обратно.

Давайте посчитаем. Допустим, средняя скорость чтения/записи 100 МиБ/с. Пусть 1 строка занимает в среднем 16 байт, тогда чтение займет приблизительно https://www.cyberforum.ru/cgi-bin/latex.cgi?16 \cdot 10^9 / 10^8 = 160 секунд. Это в теории. Но что покажет практика?

Из любопытства попробовал прочитать указанным выше способом файл 20.4 ГиБ, и это заняло 77 с. Намного лучше, чем в теории (но это не точно). В 1 минуту всё равно не укладываемся.

Думаем дальше. Узкое место тут - чтение небольшими порциями медленее, чем сразу большими блоками. Ок, пробуем считывать в бинарном режиме блоками по несколько мегабайт (выбрал 8 МиБ) и выделять записи из буфера. Теперь результат - 73 с. Так себе оптимизация, но в моем коде теперь свалка из string и stoul. gprof, настало твое время.

Анализатор показал, что почти всё собственное время выполнения программы занимает вызов stoul, остальное - ожидание данных с диска. Хорошо, выбрасываем stoul и пишем свой велосипед. Еще попытка и результат - 34.6 с. Идеально, что даже не верится. В чем же подвох? Правильно, дисковый кэш, который сильно распух за время этих тестов.

Для чистоты эксперимента сбрасываю кэш и повторяю первый и последний тест:
 файл в кэшэфайл на диске
test 177 с.165 с.
test 235 с.205 с.

Чудес не бывает.

Для желающих повторить эксперимент или сказать, что я индус
Говнокод прилагается
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <chrono>
using namespace std;
 
struct Rec {
    unsigned key;
    char data[12];
};
 
void test1() {
    ifstream fin("in.txt");
 
    unsigned n;
    fin >> n;
 
    Rec *a = new Rec[n];
 
    for (unsigned i = 0; i < n; ++i) {
        fin >> a[i].key >> a[i].data;
    }
 
    cout << a[n-1].data << endl;
}
 
void test2() {
    ifstream fin("in.txt", ios_base::in | ios_base::binary);
 
    const long SIZE = 8UL * 1024UL * 1024UL;
    char *buf = new char [SIZE];
    long size = 0;
    long pos = 0;
 
    fin.read(buf, SIZE);
    size = fin.gcount();
 
    unsigned long n = 0;
    while (isdigit(buf[pos])) {
        n = n * 10U + static_cast<unsigned>(buf[pos++] - '0');
        if (pos >= size) {
            pos = 0;
            fin.read(buf, SIZE);
            size = fin.gcount();
        }
    }
 
    Rec *a = new Rec[n];
 
    for (unsigned i = 0; i < n; ++i) {
        // Поиск начала числа.
        while (!isdigit(buf[pos])) {
            pos++;
 
            if (pos >= size) {
                pos = 0;
                fin.read(buf, SIZE);
                size = fin.gcount();
            }
        }
 
        // Чтение числа.
        a[i].key = 0;
        while (isdigit(buf[pos])) {
            a[i].key = a[i].key * 10U + static_cast<unsigned>(buf[pos++] - '0');
            if (pos >= size) {
                pos = 0;
                fin.read(buf, SIZE);
                size = fin.gcount();
            }
        }
 
        // Поиск начала текста.
        while (!isalpha(buf[pos])) {
            pos++;
            if (pos >= size) {
                pos = 0;
                fin.read(buf, SIZE);
                size = fin.gcount();
            }
        }
 
        // Чтение текста.
        unsigned wpos = 0;
        while (isalpha(buf[pos])) {
            a[i].data[wpos++] = buf[pos++];
            if (pos >= size) {
                pos = 0;
                fin.read(buf, SIZE);
                size = fin.gcount();
            }
        }
 
        a[i].data[wpos] = 0;
    }
 
    cout << a[n-1].data << endl;
}
 
void fill(unsigned n) {
    ofstream fout("in.txt");
    fout << n << endl;
 
    for (unsigned i = 0; i < n - 1; ++i) {
        fout << i + 1 << " " << "abcdefghijk" << endl;
    }
 
    fout << n << " " << "abcdefghijE" << endl;
 
    fout.close();
}
 
 
int main() {
    auto time_point_1 = std::chrono::high_resolution_clock::now();
 
/* ====================================================================================================== */
 
//    fill(1000000000);
//    test1();
    test2();
 
/* ====================================================================================================== */
 
    auto time_point_2 = std::chrono::high_resolution_clock::now();
    auto time_span = std::chrono::duration_cast<std::chrono::duration<double>>(time_point_2 - time_point_1);
    std::cout << std::setprecision(9) << std::fixed;
    std::cout << "[Completed in " << time_span.count() << " seconds]" << std::endl;
 
    return 0;
}
0
187 / 54 / 19
Регистрация: 23.12.2016
Сообщений: 167
24.02.2020, 20:00
Программа должна работать на Windows или это просто абстрактный код? Если под винду, то есть winapi функции, которые работают примерно в 50-100 раз быстрее, чем getline. Как-то тоже занимался подобный вопросом, но у меня был маленький файл в 10-15 тыс строк, он и getline читался очень быстро, время в милисекундах измерялось.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
24.02.2020, 23:31
Цитата Сообщение от roger21 Посмотреть сообщение
как быстро считать данные из файла?
getline - чрезвычайно медленный инструмент.
совершенно не годится для больших объёмов.

1.
можно открыть файл как бинарный.
и грузить сразу большими кусками.

файл, который при помощи getline вычитывался 5 минут,
в бинарном режиме был прочитан за несколько мгновений.

2.
однако, наиболее эффективный и грамотный способ: заммапить файл в память.

шиндовс
0
263 / 152 / 33
Регистрация: 29.06.2019
Сообщений: 1,524
25.02.2020, 10:04
Цитата Сообщение от roger21 Посмотреть сообщение
Потоковый ввод работает медленно.
слышала: "- чем ниже уровень языка - тем точнее и быстрее выполняется код."
может, какие С-шные варианты быстрее, чем С++ ?
или просто замена работы с string на работу c С-строками - ...
Цитата Сообщение от hoggy Посмотреть сообщение
наиболее эффективный и грамотный способ: заммапить файл в память.
встречалось https://************/questions/103061/fast-textfile-reading-in-c"
==
жаль линки не устанавливаются ?

Добавлено через 1 минуту
fooobar_com (_ заменить на .) и вставить туда, где порезан линк
0
263 / 152 / 33
Регистрация: 29.06.2019
Сообщений: 1,524
25.02.2020, 17:37
суть, видимо, как и dll находится в памяти
Image — это память, отданная под dll и exe-файлы. Каждая dll должна быть замаплена на память приложения, так что хоть она и не будет грузиться с диска или копироваться в памяти, но она отъест некоторый кусок виртуальной памяти приложения
- так и файлы можно там же...
===
всё-таки есть и недостатки
здесь нюансы - Отображение памяти - основные сведения
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.02.2020, 17:37
Помогаю со студенческими работами здесь

Быстрое заполнение большого файла
Здравствуйте! Возникла проблема в работе с большим файлом: возникла необходимость быстро заполнять некоторый участок большого файла...

Быстрое преобразование фурье wave файла
Всем доброго времени суток! Сейчас работаю над дипломом, в c++ как и в обработке звука пока новичок. На данном этапе мне необходимо...

Быстрое считывание 32кб из файла 7гб
Есть бинарный файл размером 6,95 ГБ, он представляет из себя массив short. Необходимо быстро считать случайные 65536 шортов. Т.к. весь файл...

Максимальное быстрое создание большого файла
У кого какие алгоритмы создания максимально быстро файлов, больших размеров?

Быстрое создание пустого файла определенного размера
Добрый день Столкнулся с проблемой как можно очень быстро создать файл на жестком диске, заполнены нулями (или мусором) за малый...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
BOINC: 22 года — и всё ещё работает
Programma_Boinc 12.03.2026
BOINC: 22 года — и всё ещё работает Дэвид Андерсон написал ретроспективу. Кратко: в 2001 году он ушёл из United Devices, где был CTO, и за несколько месяцев написал ядро BOINC — клиент, сервер,. . .
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru