サブクラス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を使用することができます。
メモリマップされたファイルは、OSがあなたのためにあなたのデータを仮想メモリにロードすることを可能にします。これは、サイズに関してかなり安全に単一のギガバイトの範囲にあなたを得るでしょう。あなたはこれ以上必要ですか? –
はい、詳しく教えてください。 –
私は自分で使ったことはありませんが、そこに存在を知るための十分な回答をお読みしました。 https://msdn.microsoft.com/en-us/library/ms810613.aspxに概要があります。スタックオーバーフローのためのhttp://stackoverflow.com/questions/22047673/transfering-data-through-a-memory-mapped-file-using-win32-winapi –