(利用索引)大資料查詢

親愛的張小語發表於2017-10-09

編譯環境:QT5(建立時選擇的是widget)

 主要是將一個大檔案拆成多個小檔案,這樣子就能夠大大地節省了搜尋的時間。

主要程式碼如下:

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.resize(600,400);
    w.show();

    return a.exec();
}


widget.cpp

#include "widget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMessageBox>
#include <QTextCodec>        //ASCII轉UTF-8
#include <QCursor>

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    setWindowTitle("酒店入住記錄查詢");
    label1=new QLabel();
    label1->setText("檔案大小1.27GB\n記錄數20151574");
    label2=new QLabel();
    label2->setText("請輸入要查詢的姓名:");

    btn1=new QPushButton();
    btn1->setText("查詢");
    edit1=new QLineEdit();
    text1=new QTextBrowser();

    QHBoxLayout *layout1=new QHBoxLayout();
    layout1->addWidget(label2);
    layout1->addWidget(edit1);
    layout1->addWidget(btn1);

    QVBoxLayout *layout2=new QVBoxLayout(this);
    layout2->addWidget(label1);
    layout2->addLayout(layout1);
    layout2->addWidget(text1);

    connect(btn1,SIGNAL(clicked()),this,SLOT(on_clicked()));   //將btn1與on_clicked()關聯
}

Widget::~Widget()
{

}

void Widget::select(int n)  //n==1代表查詢原始資料檔案 n==2查詢索引檔案
{
    clock_t start=clock();  //執行效率計時開始

    QTextCodec *codec=QTextCodec::codecForName("GBK");

    char key[2048]={0};
    char content[2048]={0};

    const char*s= codec->fromUnicode(edit1->text().trimmed()).data();//將edit1中的內容從QString轉化為const char*
    strcpy(key,s);

    if(strlen(key)<4)
    {
        QMessageBox::information(this,"錯誤","輸入不正確,請重新輸入");
        return;
    }
    key[strlen(key)]=',';

    char path[1024]={0};
    if(n == 1)
        strcpy(path,"D:/Documents/code/hotel/db/kaifang_noBomb.txt");
    else if(n ==2)
    {
        int index=((unsigned char)key[0]+(unsigned char)key[1]+(unsigned char)key[2]+(unsigned char)key[3])%256;
        sprintf(path,"D:/Documents/code/hotel/db/index/%d.db",index);
    }
    FILE *p=fopen(path,"r");
    if(!p)
    {
        QString str=path;
        str+="開啟失敗";
        QMessageBox::information(this,"錯誤",str);
        return ;
    }

    this->setCursor(Qt::WaitCursor);
    text1->clear();

    unsigned int count=0;   //計數器
    while(!feof(p))
    {
        memset(content,0,sizeof(content));
        fgets(content,sizeof(content),p);
        if(content[strlen(content)-1] == '\n')
            content[strlen(content)-1]=0;
        if(strncmp(content,key,strlen(key))== 0)
        {
            text1->append(codec->toUnicode(content));
            count++;
        }
    }
    clock_t end=clock();
    this->setCursor(Qt::ArrowCursor);
    fclose(p);
    QString res="找到"+QString::number(count)+"條記錄,用時"+QString::number(end-start)+"毫秒";
    QMessageBox::information(this,"完成",res);
}

void Widget::create_index()
{
    clock_t start=clock();
    char path[1024]={0};
    strcpy(path,"D:/Documents/code/hotel/db/kaifang_noBomb.txt");

    FILE *p=fopen(path,"r");
    if(!p)
    {
        QString str=path;
        str+="開啟失敗";
        QMessageBox::information(this,"錯誤",str);
        return ;
    }

    FILE *pt[256]={NULL};
    //建立256個索引檔案並開啟
    for(int i=0;i<256;i++)
    {
        memset(path,0,sizeof(path));
        sprintf(path,"D:/Documents/code/hotel/db/index/%d.db",i);
        pt[i]=fopen(path,"w");
    }
    this->setCursor(Qt::WaitCursor);

    char buf[1024]={0};
    int index=0;    //索引值
    while(!feof(p))
    {
        memset(buf,0,sizeof(buf));
        fgets(buf,sizeof(buf),p);
        if(buf[strlen(buf)-1] == '\n')
            buf[strlen(buf)-1]=0;
        //根據關鍵字求索引鍵值
        index=((unsigned char)buf[0]+(unsigned char)buf[1]+(unsigned char)buf[2]+(unsigned char)buf[3])%256;

        fprintf(pt[index],"%s\n",buf);
    }
    fclose(p);
    for(int i=0;i<256;i++)
    {
        fclose(pt[i]);
    }
    clock_t end=clock();
    this->setCursor(Qt::ArrowCursor);
    QString res="用時"+QString::number(end-start)+"毫秒";
    QMessageBox::information(this,"完成",res);
}

void Widget::on_clicked()
{
  //QMessageBox::information(this,"提示","按鈕被按了");
    select(2);
}

效果圖:

相關文章