ДТ
8 ноября 2018 г. 6:10

Чтение из большого файла

file

Проблема такая: одним из домашних заданий по программированию(первый курс) было написание блокнота. Т.е. ридера текстовых файлов. Это я, собственно, сделал, но есть небольшой нюанс - при открытии ОЧЕНЬ больших файлов (например, если в диалоговом окне выбора файла написать *.* , то можно будет, в обход запрету на разрешение файлов, открыть какой-нибудь блю-рей фильм на 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
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
6

Сдаётся мне, что у вас на ПК просто память кончается, а в обычном блокноте там каким-то способом реализована частичная подгрузка.

Просто QString tmpStr сам по себе не в состоянии съесть 30 гигабайт за раз, скорее всего падает в цикле while, надо проверять это момент, но наверняка там.

Тут вопрос в том, что вы хотите? Я бы сделал дополнительную проверку на тип файла и возможно размер и запретил бы открывать такой файл.


0
IF

Доброго времени суток.

Вы используете очень скользкий путь чтения файла(цикл пока не конец).

в цикле открывать файл на чтение и забирать по 10000 позиций - вот главная ошибка. А с кодом 3 он вылетает скорее всего потому что у вас оперативная память кончается - и идёт запрос на жёсткий диск, далее несколько больших запросов и ядро просит удалить данный процесс.


Евгений как всегда прав, что вам советует проверять на объём файла при считывании, и то что вы используете регулярные выражения для взятия файла - это скорее хак, который скорее всего можно как то попросить менеджер отключить( как всегда отправляю в документацию).


1
  • 8 ноября 2018 г. 13:47

Учитывая вышесказанное могу добавить,что необходимо читать из файла как минимум блоками,размером с буфер страницы,и выводить в текстовое поле виджета или как там у тебя реализовано по-блочно,ну и вообще надо полагать как минимум из аппаратных возможностей,если у тебя 4 гига ОЗУ,а ты пытаешься в него загрузить 30 GB,то эо не есть нормально.

0
ДТ

Чуть переписал код, программа, ожидаемо, перестала падать при открытии больших файлов. Но все равно зависает при попытке открыть хоть сколько-нибудь большой файл. А дожидаться открытия я уж не стал. Стыдно, на самом деле, что я сам не подумал о том, что скидывать всё в одну строку - глупо.

Хотя стандартный блокнот, опять же, довольно резво открыл экзешник на 900 мб, когда моя поделка попросту захлебнулась. Мне все еще интересно, каким образом это сделано там.


QString tempStr;
        ui->_mainTextField->clear();
        while(!stream.atEnd())
        {
            tempStr.append(stream.read(10000));
            if(tempStr.size() >= 100000)
            {
                ui->_mainTextField->append(tempStr);
                tempStr.clear();
            }
        }
        ui->_mainTextField->append(tempStr);
        changesIs = false; 

0

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

Как сайты подгружают контент по мере прокрутки страницы

1
IF

Доброго времени суток.


Евгений прав.


Вам надо перестроить приложение нарпимер по такой логике.


У вас есть поле - куда вы выводите содержимое текстового файла, рассчитываете сколько символов помещается на "данный момент" в окно.

Далее открываете файл на чтение и считываете сколько всего занимает данный файл - и выполняете "разметку скролбара".


Под "разметкой скролбара" приведу пример:

Например у вас есть файл, в нём 1000 символов, а в окно помещается 100, получается , что полоска скролбара дожна занимать на данный момент 100/1000 - 1/10 часть всего скролбара.


Далее вы выполняете отрисовку тех самый(из примера) 100 символов на сцену.


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

При передвижении скролбара вы вычисляете верхнюю и нижнюю границу выводимую на экран текстового файла и запрашиваете в контейнер из файла - далее выводите на экран.

Воздможно улучшение например в качестве хэширования данных при запросе из файла - это ускорит приложение, но займёт чуть больше памяти при хранении данных - ЗА СЁ НУЖНО ПЛАТИТЬ.


Хорошего дня и удачи в кодинге.



2

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
МБ
14 июля 2019 г. 17:57
Максим Беликов

C++ - Тест 005. Структуры и Классы

  • Результат:100баллов,
  • Очки рейтинга10
МБ
14 июля 2019 г. 17:52
Максим Беликов

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:90баллов,
  • Очки рейтинга8
МБ
14 июля 2019 г. 17:45
Максим Беликов

C++ - Тест 003. Условия и циклы

  • Результат:71баллов,
  • Очки рейтинга1
Последние комментарии
16 июля 2019 г. 15:15
Евгений Легоцкой

Конечно )) На самом деле не все читали Шлее... я например не читал ))
16 июля 2019 г. 15:05
IscanderChe

Так пример с QLocalServer и QLocalSocket я целиком переписал с QTcpSocket и QTcpServer из книги Шлее. Принципиальное отличие - где коннект ставить. :)) Разве что на это упор сделать. Но я могу...
16 июля 2019 г. 14:47
Евгений Легоцкой

Лучше API ))) Кстати, по использованию QLocalServer и QLocalSocket на сайте нет статей, было бы очень полезно и хорошо пошло бы в раздел Qt.
16 июля 2019 г. 12:36
IscanderChe

Да, прямой доступ не предполагается. Впрочем, можно, конечно, и напрямую. Всё равно всё локально происходит. Проблема в том, как донести сведения об изменениях в базе, которые вносит клиент, д...
b
16 июля 2019 г. 8:38
bbb116

спасибо, до smart pointer еще не дошел )
Сейчас обсуждают на форуме
17 июля 2019 г. 11:49
Михаиллл

В настройкак указан индификатор проекта и ключ. Осталось понять как использовать ключ. Попробовал вставить в этот запрос 'https://[PROJECT_ID].firebaseio/users/jack/name.json?access_to...
b
17 июля 2019 г. 9:01
bbb116

Вообщем работает только если делать setSceneRect только в конструкторе главного окна, если потом менять rect например при вставке картинки то появляются сколлы все как надо только области не р...
17 июля 2019 г. 5:54
Алексей Внуков

хочу не стандартный набор символов, а все ненужное убрать чтоб не мешало. для начала решил посмотреть как работает клава на родном примере, а он на телефоне не взлетел вот и начал разби...
17 июля 2019 г. 5:06
Михаиллл

Добрый день.Возможно вы сталкивались с облаками.Нужно из Qt создавать на облаке папки, записывать в папки файлы, читать и удалять с компьютера файлы.Возможно знаете, что лучше и проще испол...
Ищу работу?
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы

EVILEG
О нас
Услуги
Присоединяйтесь к нам
© EVILEG 2015-2019
Рекомендует хостинг TIMEWEB