Русский / Russian English / Английский

Сейчас на форуме: (+4 невидимых)
 · Начало · Статистика · Регистрация · Поиск · ПРАВИЛА ФОРУМА · Язык · RSS ·

 eXeL@B —› Программирование —› Записать / считать вектор из файла (c++)
Посл.ответ Сообщение


Ранг: 213.9 (наставник)
Статус: Участник
X-Literator

Создано: 7 апреля 2017 05:57 · Поправил: Crawler New!
Цитата · Личное сообщение · #1

Привет.

Есть программа, которая читает очень много строк из файла в vector<string>.

Это крайне долго.

Вопрос: как записать вектор в файл так, чтобы потом его можно было тупо считать из файла одним куском в буфер памяти, а затем сделать из этого куска вектор - сразу, как со структурой, которую ты считываешь и пользуешься через указатель?
С каким-нибудь char-массивом это понятно и легко, а с вектором я что-то туплю.

Спасибо.


Ранг: 1024.6 (!!!!)
Статус: Участник

Создано: 7 апреля 2017 07:10 New!
Цитата · Личное сообщение · #2

нечеткая задача которая имеет множества решений
1) не использовать вектор. написать свой оптимизированный
2) использовать вектор. заранее делая большой reverve
3) использовать вектор читая данные из памяти. а не из файла. которые предварительно туда загружены(в память)
4) написать свой аллокатор для вектора. который будет юзать к мемори мап для быстрого доступа к данным
итд...фантазиям нет предела


Ранг: 213.9 (наставник)
Статус: Участник
X-Literator

Создано: 7 апреля 2017 07:19 · Поправил: Crawler New!
Цитата · Личное сообщение · #3

reversecode
А что тут нечеткого? Нужно записать вектор в файл, а потом целиком считать его.

1) нет смысла, лучше не выйдет;
2) reserve почти не влияет на скорость процесса, проверено clock()
3) совсем не влияет на скорость, т.к. файл в современных ОС почти наверняка читается из памяти;
4) надо подумать

Ранг: 0.0 (гость)
Статус: Участник

Создано: 7 апреля 2017 08:07 New!
Цитата · Личное сообщение · #4

вам нужна сериализация.
как пример, если нужно что то сложнее гугл в помощь.

Ранг: 409.4 (мудрец)
Статус: Участник

Создано: 7 апреля 2017 11:34 · Поправил: dosprog New!
Цитата · Личное сообщение · #5

Crawler пишет:
4) надо подумать

Так 4) это же считай то же, что и 3) , только от (с)микрософта...
самое внушительно звучит это 1), если при предыдущем сохранении на диске строки там проиндексированы.
Без предварительной индексации на какой-то выигрыш по времени вряд ли удастся расчитывать


Ранг: 148.0 (ветеран)
Статус: Участник

Создано: 7 апреля 2017 12:25 New!
Цитата · Личное сообщение · #6

Crawler пишет:
1) нет смысла, лучше не выйдет;

Лучше не выйдет, если ты напишешь такую же реализацию, но если писать под задачу, скорость вырастет на порядки. Например, можно хранить строки одним массивом, где они будут разделены нулем, а в векторе хранить только указатели на начало каждой строки. Так, выделение памяти, чтение и запись в файл будут выполняться одним вызовом апи, но после чтения нужно будет в дополнительном цикле пробежаться по массиву данных и построить массив указателей.

Ранг: 0.0 (гость)
Статус: Участник

Создано: 7 апреля 2017 12:33 New!
Цитата · Личное сообщение · #7

rmn пишет: Лучше не выйдет

Поддерживаю. Если вектор начинает упираться в скорость, нужно не решать проблему через задницу, пытаясь заставить делать vector то для чего он в принципе не предназначен. Раз данных много и появилась подобная проблема, лучше подумать о какой то мелкой базе, а не делать очередной велосипед с квадратными колесами.


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 7 апреля 2017 12:49 New!
Цитата · Личное сообщение · #8

Crawler

Вариант 3, который советовал reversecode. Поясню в деталях:

1. Берём файл на диске (он представляет собой набор строк, разделённых каким-нибудь \n или \r\rn) и маппим его целиком без разбора в память.
2. Читаем строки (которые пока являются const char[]) в объекты типа std::string и кладём их в вектор.
3. Анмапим файл.

Ранг: 582.9 (!)
Статус: Модератор

Создано: 7 апреля 2017 12:58 New!
Цитата · Личное сообщение · #9

rmn
Это ничем не отличается от vector<const char* const> и не надо свое ничего писать. Вычитываем в один vector<uint8_t> и дальше мапим вектор указателей на первый. Но в таком случае если данные изменяются нужно городить свой велосипед с COW (copy-on-write). А если не изменяются проще вообще отказаться от vector<string> в пользу const char* const[].

Ранг: 148.0 (ветеран)
Статус: Участник

Создано: 7 апреля 2017 13:24 New!
Цитата · Личное сообщение · #10

r_e пишет:
Это ничем не отличается от vector<const char* const> и не надо свое ничего писать.

Это отличается от vector<string>, где нужно будет столько раз вызвать аллокатор, сколько строк в массиве.


Ранг: 213.9 (наставник)
Статус: Участник
X-Literator

Создано: 7 апреля 2017 14:09 New!
Цитата · Личное сообщение · #11

ARCHANGEL, да не повысит это производительность.

Я сам тестировал это только вчера, но сильно подозревал заранее, что ничего не выйдет. Так и вышло. Наверняка реализация функции чтения так и делает. Не терзает же она жесткий диск.


Ранг: 669.3 (! !)
Статус: Участник
ALIEN Hack Team

Создано: 7 апреля 2017 14:12 New!
Цитата · Личное сообщение · #12

Crawler
Покажи народу код и образец файла. Может, что-то и порешается.

Ранг: 0.0 (гость)
Статус: Участник

Создано: 7 апреля 2017 14:19 New!
Цитата · Личное сообщение · #13

я бы взял https://sqlite.org/inmemorydb.html миллионы записей спокойно вертит и нет проблем с чтением\записью.


Ранг: 1024.6 (!!!!)
Статус: Участник

Создано: 7 апреля 2017 17:30 New!
Цитата · Личное сообщение · #14

когда ставится задача в лоб - хочу хрустальным шариком забивать гвозди и при этом его не разбить
то нужно задачу с самого нуля пересматривать,
может там и не вектор нужен, может там нужно что то по другом переделывать
а не пытаться это все пропихнуть через вектор


Ранг: 213.9 (наставник)
Статус: Участник
X-Literator

Создано: 7 апреля 2017 20:23 · Поправил: Crawler New!
Цитата · Личное сообщение · #15

Всем спасибо.

Решил действительно не совсем через вектор, REVERSECODE тут оказался прав.

Сначала посчитал максимально возможную длину строки из текстового файла, потом переделал файл в другой формат с фиксированной длиной строки. Если строка была меньше максимальной длины, она дополнялась нолями.

То есть всё было записано в char [25].

Получившийся файл считываю в память целиком, потом создаю массив вроде такого:

Code:
  1. unsigned int number_of_strings = filesize/25;
  2. char **strings = new char *[number_of_strings];


А потом просто создаю вектор (для удобства работы, хотя это уже на фиг не нужно):

Code:
  1. vector <string *> str_pointers;


И присваиваю ему указатели на char-строки. Работает:

Code:
  1. for (int i=0; i<number_of_strings; i++)
  2. {
  3.   str_pointers.push_back((string *) &strings[i]);
  4. }


Получилось во много раз быстрее, чем каждый раз читать строки из файла и пушить в вектор.

Ранг: 409.4 (мудрец)
Статус: Участник

Создано: 7 апреля 2017 20:29 · Поправил: dosprog New!
Цитата · Личное сообщение · #16

Не намного хуже была бы реализация с индексированием при предыдущем сохранении.
Головняка побольше зато в разы меньше места займёт на диске..

| Сообщение посчитали полезным: Crawler

 eXeL@B —› Программирование —› Записать / считать вектор из файла (c++)

Видеокурс ВЗЛОМ