Чтение из большого файла
Проблема такая: одним из домашних заданий по программированию(первый курс) было написание блокнота. Т.е. ридера текстовых файлов. Это я, собственно, сделал, но есть небольшой нюанс - при открытии ОЧЕНЬ больших файлов (например, если в диалоговом окне выбора файла написать *.* , то можно будет, в обход запрету на разрешение файлов, открыть какой-нибудь блю-рей фильм на 30+ гб), программа погибает в агонии и с криками ( код ошибки : 3). Причем, если открывать нормальным блокнотом, что идет вместе с виндой, то он спокойно "переваривает" любой блю-рей. Каким образом это можно решить?
QFile file(QFileDialog::getOpenFileName(this,"Открыть файл","C:\\", tr("Текстовые файлы (*.txt);;Файлы C++ (*.cpp *.h)"))); if (!file.open(QFile::ReadOnly | QFile::Text)) return; QTextStream stream(&file); stream.setCodec("UTF-8"); QString tempStr; while(!stream.atEnd()) tempStr.append(stream.read(10000)); ui->_mainTextField->setText(tempStr); MainWindow::setWindowTitle(file.fileName()); fileName = file.fileName(); tempStr = nullptr; file.flush(); file.close();
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.Вам це подобається? Поділіться в соціальних мережах!
- Akiv Doros
- 12 листопада 2024 р. 01:58
C++ - Тест 004. Указатели, Массивы и Циклы
- Результат:50бали,
- Рейтинг балів-4
- molni99
- 26 жовтня 2024 р. 11:37
C++ - Тест 004. Указатели, Массивы и Циклы
- Результат:80бали,
- Рейтинг балів4
- molni99
- 26 жовтня 2024 р. 11:29
C++ - Тест 004. Указатели, Массивы и Циклы
- Результат:20бали,
- Рейтинг балів-10
Сдаётся мне, что у вас на ПК просто память кончается, а в обычном блокноте там каким-то способом реализована частичная подгрузка.
Просто QString tmpStr сам по себе не в состоянии съесть 30 гигабайт за раз, скорее всего падает в цикле while, надо проверять это момент, но наверняка там.
Тут вопрос в том, что вы хотите? Я бы сделал дополнительную проверку на тип файла и возможно размер и запретил бы открывать такой файл.
Доброго времени суток.
Вы используете очень скользкий путь чтения файла(цикл пока не конец).
в цикле открывать файл на чтение и забирать по 10000 позиций - вот главная ошибка. А с кодом 3 он вылетает скорее всего потому что у вас оперативная память кончается - и идёт запрос на жёсткий диск, далее несколько больших запросов и ядро просит удалить данный процесс.
Евгений как всегда прав, что вам советует проверять на объём файла при считывании, и то что вы используете регулярные выражения для взятия файла - это скорее хак, который скорее всего можно как то попросить менеджер отключить( как всегда отправляю в документацию).
Учитывая вышесказанное могу добавить,что необходимо читать из файла как минимум блоками,размером с буфер страницы,и выводить в текстовое поле виджета или как там у тебя реализовано по-блочно,ну и вообще надо полагать как минимум из аппаратных возможностей,если у тебя 4 гига ОЗУ,а ты пытаешься в него загрузить 30 GB,то эо не есть нормально.
Чуть переписал код, программа, ожидаемо, перестала падать при открытии больших файлов. Но все равно зависает при попытке открыть хоть сколько-нибудь большой файл. А дожидаться открытия я уж не стал. Стыдно, на самом деле, что я сам не подумал о том, что скидывать всё в одну строку - глупо.
Хотя стандартный блокнот, опять же, довольно резво открыл экзешник на 900 мб, когда моя поделка попросту захлебнулась. Мне все еще интересно, каким образом это сделано там.
Думаю, что в блокноте частичная загрузка не в цикле, а по событию скролбара, вполне возможно, что он считывает необходимую информацию по мере прокрутки.
Как сайты подгружают контент по мере прокрутки страницы
Доброго времени суток.
Евгений прав.
Вам надо перестроить приложение нарпимер по такой логике.
У вас есть поле - куда вы выводите содержимое текстового файла, рассчитываете сколько символов помещается на "данный момент" в окно.
Далее открываете файл на чтение и считываете сколько всего занимает данный файл - и выполняете "разметку скролбара".
Под "разметкой скролбара" приведу пример:
Например у вас есть файл, в нём 1000 символов, а в окно помещается 100, получается , что полоска скролбара дожна занимать на данный момент 100/1000 - 1/10 часть всего скролбара.
Далее вы выполняете отрисовку тех самый(из примера) 100 символов на сцену.
Евгений подчеркнул, что нужно увязать сигнал передвижения скролбара и слот перерисовки сцены.
При передвижении скролбара вы вычисляете верхнюю и нижнюю границу выводимую на экран текстового файла и запрашиваете в контейнер из файла - далее выводите на экран.
Воздможно улучшение например в качестве хэширования данных при запросе из файла - это ускорит приложение, но займёт чуть больше памяти при хранении данных - ЗА СЁ НУЖНО ПЛАТИТЬ.
Хорошего дня и удачи в кодинге.