2017-05-03 22 views
2

我有一个文本区域,我动态填充(具体我有QP QPlainTextEdit,但它对算法建议不重要)。分裂大量的文本数据的算法

现在问题有时会出现大量数据,随着更多数据进入我的应用程序变得沉重,因为所有的文本数据都在主内存中。

所以我想到了以下几点。我们可以使用一个文件来存储所有的文本数据并动态地显示有限数量的数据,但同时我不得不幻想用户数据大小是文件的大小,通过创建滚动事件来触发新行谈到。

有没有这种问题的标准算法?

+0

内存映射文件允许操作系统加载nad将您的数据卸载到虚拟内存中。这将使您在尺寸方面非常安全地进入单一技嘉范围。你需要比这更多吗? –

+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,通过改变委托来实现所需的单元格可视化。请注意,您必须使用QTableView,因为其他QAbstractItemView s已打碎物品回收,并且不能很好地处理超大型号(QTableView不存在此类问题)。

一段时间自我我写了大文件的十六进制查看器,并测试了文件大小为2GB,它的工作完美。

好吧,我发现我的旧代码,可能是一个很好的例子:

#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

这是我的两分钱,

当我用Google搜索了类似的问题,我发现从Fast textfile reading in c++

总之答案,内存在升压库映射文件。不仅可以提高性能,而且可以处理大量数据。

链接中的示例中,我可以检查行数并从Lib获取数据。

好运