ДТ
Даниил Тетерин8. November 2018 06: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();

Screenshot_2.png
Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

6
Evgenii Legotckoi
  • 8. November 2018 08:09

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

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

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


    IF
    • 8. November 2018 10:31

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

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

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


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


      linq
      • 8. November 2018 13:47

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

        ДТ
        • 11. November 2018 15:09

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

        Хотя стандартный блокнот, опять же, довольно резво открыл экзешник на 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; 

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

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

            IF
            • 12. November 2018 04:37

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


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


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


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

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


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

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


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


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

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

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


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



              Kommentare

              Nur autorisierte Benutzer können Kommentare posten.
              Bitte Anmelden oder Registrieren
              Letzte Kommentare
              A
              ALO1ZE19. Oktober 2024 15:19
              Fb3-Dateileser auf Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
              ИМ
              Игорь Максимов5. Oktober 2024 14:51
              Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
              d
              dblas55. Juli 2024 18:02
              QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
              k
              kmssr9. Februar 2024 02:43
              Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
              Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
              Jetzt im Forum diskutieren
              J
              JacobFib17. Oktober 2024 10:27
              добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
              JW
              Jhon Wick1. Oktober 2024 22:52
              Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
              КГ
              Кирилл Гусарев27. September 2024 16:09
              Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
              F
              Fynjy22. Juli 2024 11:15
              при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

              Folgen Sie uns in sozialen Netzwerken