2017-05-03 7 views
2

私は動的に取り込むテキスト領域を持っています(具体的にはです.QPlainTextEditはQtですが、アルゴリズムの提案は重要ではありません)。大量のテキストデータを分割するためのアルゴリズム

問題が発生する場合があります。大量のデータがあり、アプリケーション内のデータが増えると、すべてのテキストデータがメインメモリに格納されます。

私は次のことを考えました。私たちは、すべてのテキストデータを格納するためにファイルを使用し、限られた量のデータのみを動的に表示することができますが、同時に、データサイズがファイルのものであることをユーザに納得させる必要があります。来る。

このような問題の標準アルゴリズムはありますか?

+0

メモリマップされたファイルは、OSがあなたのためにあなたのデータを仮想メモリにロードすることを可能にします。これは、サイズに関してかなり安全に単一のギガバイトの範囲にあなたを得るでしょう。あなたはこれ以上必要ですか? –

+0

はい、詳しく教えてください。 –

+0

私は自分で使ったことはありませんが、そこに存在を知るための十分な回答をお読みしました。 https://msdn.microsoft.com/en-us/library/ms810613.aspxに概要があります。スタックオーバーフローのためのhttp://stackoverflow.com/questions/22047673/transfering-data-through-a-memory-mapped-file-using-win32-winapi –

答えて

1

サブクラスQAbstractListModelがキャッシュを実装しています。 セルの値が読み取られると、キャッシュからデータをフェッチし、値がキャッシュに存在しない場合は更新します。

微調整QTableView、代理人を変更して必要なセルの視覚化を達成することによって。他のQAbstractItemViewは破損したアイテムがリサイクルされており、非常に大きなモデルはうまく扱えないため、QTableViewを使用する必要があります(QTableViewにはこのような問題はありません)。

私は大きなファイルの16進数ビューアを書き、ファイルサイズ2GBでそれが完全に動作していることをテストしました。

[OK]を、私は良い例かもしれない私の古いコードを見つけた:ここ

#include <QAbstractTableModel> 

class LargeFileCache; 

class LageFileDataModel : public QAbstractTableModel 
{ 
    Q_OBJECT 
public: 
    explicit LageFileDataModel(QObject *parent); 

    // QAbstractTableModel 
    int rowCount(const QModelIndex &parent) const; 
    int columnCount(const QModelIndex &parent) const; 
    QVariant data(const QModelIndex &index, int role) const; 

signals: 

public slots: 
    void setFileName(const QString &fileName); 

private: 
    LargeFileCache *cachedData; 
}; 

// ----- cpp file ----- 
#include "lagefiledatamodel.h" 
#include "largefilecache.h" 
#include <QSize> 

static const int kBytesPerRow = 16; 

LageFileDataModel::LageFileDataModel(QObject *parent) 
    : QAbstractTableModel(parent) 
{ 
    cachedData = new LargeFileCache(this); 
} 

int LageFileDataModel::rowCount(const QModelIndex &parent) const 
{ 
    if (parent.isValid()) 
     return 0; 
    return (cachedData->FileSize() + kBytesPerRow - 1)/kBytesPerRow; 
} 

int LageFileDataModel::columnCount(const QModelIndex &parent) const 
{ 
    if (parent.isValid()) 
     return 0; 
    return kBytesPerRow; 
} 

QVariant LageFileDataModel::data(const QModelIndex &index, int role) const 
{ 
    if (index.parent().isValid()) 
     return QVariant(); 
    if (index.isValid()) { 
     if (role == Qt::DisplayRole) { 
      qint64 pos = index.row()*kBytesPerRow + index.column(); 
      if (pos>=cachedData->FileSize()) 
       return QString(); 
      return QString("%1").arg((unsigned char)cachedData->geByte(pos), 2, 0x10, QChar('0')); 
     } else if (role == Qt::SizeHintRole) { 
      return QSize(30, 30); 
     } 
    } 

    return QVariant(); 
} 

void LageFileDataModel::setFileName(const QString &fileName) 
{ 
    beginResetModel(); 
    cachedData->SetFileName(fileName); 
    endResetModel(); 
} 

は、キャッシュの実装です:

class LargeFileCache : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit LargeFileCache(QObject *parent = 0); 

    char geByte(qint64 pos); 
    qint64 FileSize() const; 

signals: 

public slots: 
    void SetFileName(const QString& filename); 

private: 
    static const int kPageSize; 

    struct Page { 
     qint64 offset; 
     QByteArray data; 
    }; 

private: 
    int maxPageCount; 
    qint64 fileSize; 

    QFile file; 
    QQueue<Page> pages; 
}; 

// ----- cpp file ----- 
#include "largefilecache.h" 

const int LargeFileCache::kPageSize = 1024*4; 

LargeFileCache::LargeFileCache(QObject *parent) 
    : QObject(parent) 
    , maxPageCount(1024) 
    , fileSize(0) 
{ 

} 

char LargeFileCache::geByte(qint64 pos) 
{ 
    // largefilecache 
    if (pos>=fileSize) 
     return 0; 

    for (int i=0, n=pages.size(); i<n; ++i) { 
     int k = pos - pages.at(i).offset; 
     if (k>=0 && k< pages.at(i).data.size()) { 
      pages.enqueue(pages.takeAt(i)); 
      return pages.back().data.at(k); 
     } 
    } 

    Page newPage; 
    newPage.offset = (pos/kPageSize)*kPageSize; 
    file.seek(newPage.offset); 
    newPage.data = file.read(kPageSize); 
    pages.push_front(newPage); 

    while (pages.count()>maxPageCount) 
     pages.dequeue(); 

    return newPage.data.at(pos - newPage.offset); 
} 

qint64 LargeFileCache::FileSize() const 
{ 
    return fileSize; 
} 

void LargeFileCache::SetFileName(const QString &filename) 
{ 
    file.close(); 
    pages.clear(); 
    file.setFileName(filename); 
    file.open(QFile::ReadOnly); 
    fileSize = file.size(); 
} 

私は行データを処理していたので、私は手動でキャッシュを書きました、キャッシングロジックの作成に役立つQCacheを使用することができます。

+0

答えをありがとう。あなたは次の投稿で私を助けてくれますか: –

+0

http://stackoverflow.com/questions/43789582/how-to-produce-illusion-effect-in-scrolling-in-qt –

0

mmapを使用するのは、ファイルをメモリに保存している間だけ読み取る方法だけです。エディットコントロールには一度にいくつかの部分しか含まれません。

このようなシステムは、関連するテキスト編集ウィジェットにかなり固有のものだと考える必要があります。この場合、希望する機能を使ってQPlainTextEditを拡張する方法を理解するか、新しいテキスト編集ウィジェットを作成する必要があります(既存のものをフォークする可能性があります)。オープンソースとして利用可能な多数のテキスト編集ウィジェットがあり、これを出発点として使用することができます。

私はこの大きなファイルのテキストを編集したいと思っています。読み取り専用のビューアとしてQPlainTextEditしか使用していない場合は、大きなテキストストリームの読み込みウィジェットである独自のものを書くことは、既存のエディタウィジェットを拡張するよりはるかに簡単です。

0

それは私の2セント、

私は同様の質問をGoogleで検索すると、私は要するにFast textfile reading in c++

から答えを見つけた、メモリはブーストlibにファイルをマッピングしています。パフォーマンスだけでなく、大量のデータを処理するのにも役立ちます。

リンクのサンプルでは、​​行数を確認してLibからデータを取得できました。

幸運

関連する問題