Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Загрузка большого текстового файла
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
ALeXUI
Здравствуйте, столкнулся со следующей проблемой.
Необходимо загрузить и обработать, большой текстовый файл, примерно 20 мб.
И желательно его вывести, например, в qtextedit или что-нибудь подобное.

Самы простой вариант дико загружает компьютер:


        QFile Filetxt;
        Filetxt.setFileName(PathName);
        Filetxt.open(QIODevice::ReadOnly);
        QTextStream textStream;
        textStream.setDevice(&Filetxt);        
        MainTextEdit->append(textStream.readAll());
        Filetxt.close();








Подскажиет пожалуйста, как это сделать лучше?

Нужно распарсить каждую строчку, там находятся данные, по которым строить графики.
Snake174
Я создавал буфер для содержимого файла char *data = new char[ file_size ], читал в него содержимое и в QTextEdit выводил только ту часть, которая видна в данный момент. Если в QTextEdit влазит, например 20 строк, то зачем показывать все остальные. Это как при программировании графики, когда нужно отсекать то, что не попадает в камеру, чтобы лишнее не рисовалось. Файлы были размером до 200 Мб и всё летало. Я так понял дико загружает компьютер то, что в QTextEdit постоянно грузятся данные и Qt пытается всё это перерисовывать.
_Vitaliy_
Все зависит от того, какого рода содержимое файла. Если это к примеру данные, структура которых повторяется в каждой строке то считывается строка, затем парсится и записывается в например в модель. Если это Вам подходит то могу скинуть часть кода (если сами не разберетесь).
ALeXUI
Цитата
Если в QTextEdit влазит, например 20 строк, то зачем показывать все остальные. Это как при программировании графики, когда нужно отсекать то, что не попадает в камеру, чтобы лишнее не рисовалось.


Не могли бы привести кучовек кода, не могу понять, как это реализовать?) Но идея мне нравиться)

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


Да так и есть, структура повторяется в каждой строчке. Буду очень благодарен за пример кода)
Snake174
Создаёшь скроллбар, ставишь его рядом с QTextEdit-ом:
scrollBar = new QScrollBar( ... );
scrollBar->setOrientation( Qt::Vertical );
connect( scrollBar, SIGNAL(valueChanged(int)), this, SLOT(sbValueChanged(int)) );


Раскрывающийся текст

//------------------------------------------------------------------------------
void MainWindow::sbValueChanged( int value )
{
  TextEdit *viewer = dynamic_cast<TextEdit *>( pTabs->currentWidget() );

  int ind = pTabs->tabToolTip( pTabs->currentIndex() ).toInt();
  int cnt = 0;
  int pos = 0;
  int pos1 = 0;

  int mib = encodingComboBox->itemData( encodingComboBox->currentIndex() ).toInt();
  QTextCodec *codec = QTextCodec::codecForMib( mib );
  QTextStream in( &encodedData[ ind ] );

  in.setAutoDetectUnicode( false );
  in.setCodec( codec );

  QByteArray::ConstIterator itEnd = encodedData[ ind ].constEnd();

  for (QByteArray::ConstIterator it = encodedData[ ind ].constBegin(); it != itEnd; ++it)
  {
    if (*it == '\n')
      ++cnt;

    if (cnt == value)
    {
      pos = std::distance( encodedData[ ind ].constBegin(), it );
      cnt = 0;

      do
      {
        ++it;

        if (it == itEnd)
        {
          pos1 = std::distance( encodedData[ ind ].constBegin(), it );
          break;
        }

        if (*it == '\n')
          ++cnt;
      }
      while (cnt != visibleRowCount);

      pos1 = std::distance( encodedData[ ind ].constBegin(), it );

      break;
    }
  }

  in.seek( pos );
  viewer->clear();
  viewer->appendPlainText( in.read( pos1 - pos ) );
  in.device()->close();
}
//------------------------------------------------------------------------------
void MainWindow::resizeEvent( QResizeEvent *event )
{
  TextEdit *viewer = dynamic_cast<TextEdit *>( pTabs->currentWidget() );
  QFontMetrics fm( viewer->font() );

  visibleRowCount = viewer->height() / fm.height();

  QMainWindow::resizeEvent( event );
}
//------------------------------------------------------------------------------
// После загрузки файла в encodedData вызываешь этот слот
void MainWindow::updateTextEdit()
{
  TextEdit *viewer = dynamic_cast<TextEdit *>( pTabs->currentWidget() );
  viewer->clear();

  int mib = encodingComboBox->itemData( encodingComboBox->currentIndex() ).toInt();
  QTextCodec *codec = QTextCodec::codecForMib( mib );
  int ind = pTabs->tabToolTip( pTabs->currentIndex() ).toInt();
  QTextStream in( &encodedData[ ind ] );

  int data_size = encodedData[ ind ].size();
  int bytesToRead = 0;
  rowCount = 0;

  QByteArray::ConstIterator itEnd = encodedData[ ind ].constEnd();

  for (QByteArray::ConstIterator it = encodedData[ ind ].constBegin(); it != itEnd; ++it)
  {
    if (*it == '\n')
      ++rowCount;

    if (rowCount == visibleRowCount || it == itEnd)
      bytesToRead = std::distance( encodedData[ ind ].constBegin(), it );
  }

  viewer->appendPlainText( in.read( bytesToRead ) );

  scrollBar->setMaximum( rowCount );

  viewer->moveCursor( QTextCursor::Start );
}



encodedData - массив QByteArray

У QTextEdit-a делаешь:
setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );

Ну что-то типа этого у меня было.
_Vitaliy_
У меня данные в строке разделялись как минимум одним пробелом. Если у Вас это так, то действовать можно по следующему алгоритму.
1. в *.h пишем: QStandardItemModel *model;
2. в *.cpp в конструкторе: model = new QStandardItemModel(this);
3. здесь привожу часть своего рабочего кода (некоторые "вещи" опущены) главное уловить смысл
Раскрывающийся текст
int currentRow = 0;
QCoreApplication::processEvents(); // chtobi prilozhenie ne zavisal

QStandardItem *item = 0;
while (!stream.atEnd())
{
fields = stream.readLine().simplified().split(' '); // razdelitel !!!
for (int i = 0; i < columnCount; ++i)
{
item = new QStandardItem(fields.at(i));
model->setItem(currentRow, i, item);
}
++currentRow;
}

4. далее по коду, например у меня это было отдельное окно
Раскрывающийся текст
QDialog *dialog = new QDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setWindowTitle("Data ...");
...

QTableView *view = new QTableView(dialog); /// QTableView (&dialog)
view->setModel(model);
...

dialog->show();

удобно тем, что данные хранятся в модели, а с моделью довольно просто работать.
ALeXUI
Vitaliy, огромное Вам спасибо, вернулся к этой задаче, и все получилось очень здорово!
Гость
Цитата(Snake174 @ 18.12.2012, 4:28) *
Я создавал буфер для содержимого файла char *data = new char[ file_size ], читал в него содержимое и в QTextEdit выводил только ту часть, которая видна в данный момент. Если в QTextEdit влазит, например 20 строк, то зачем показывать все остальные. Это как при программировании графики, когда нужно отсекать то, что не попадает в камеру, чтобы лишнее не рисовалось. Файлы были размером до 200 Мб и всё летало. Я так понял дико загружает компьютер то, что в QTextEdit постоянно грузятся данные и Qt пытается всё это перерисовывать.


Не так уж и летает! Реализовал Ваш алгоритм. Если просматривать файл в 200 Mb, то конец файла очень медлительный. Это и не удивительно - так как постоянно приходится проходить весь файл при вычислении значения pos
Snake174
Цитата(Гость @ 13.9.2013, 9:20) *
Цитата(Snake174 @ 18.12.2012, 4:28) *
Я создавал буфер для содержимого файла char *data = new char[ file_size ], читал в него содержимое и в QTextEdit выводил только ту часть, которая видна в данный момент. Если в QTextEdit влазит, например 20 строк, то зачем показывать все остальные. Это как при программировании графики, когда нужно отсекать то, что не попадает в камеру, чтобы лишнее не рисовалось. Файлы были размером до 200 Мб и всё летало. Я так понял дико загружает компьютер то, что в QTextEdit постоянно грузятся данные и Qt пытается всё это перерисовывать.


Не так уж и летает! Реализовал Ваш алгоритм. Если просматривать файл в 200 Mb, то конец файла очень медлительный. Это и не удивительно - так как постоянно приходится проходить весь файл при вычислении значения pos

Ты бы ещё лет через 5 ответ написал. К тому же _Vitaliy_ предложил отличный вариант, сделал также, всем доволен.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.