利用QBuffer和QLinkedList做数据块存储队列

  Qt中QByteArray存储数据很方便,使用QBuffer存储大块数据更方便。QBuffer类包装了QByteArray类对象,实际存储还是使用了QByteArray,但QBuffer实现了QIODevice接口,其拥有丰富的读写接口,使操作更方便。

  主要需求是,存进去的数据接口函数参数要求是char* dat 和int datalength是形式,取出来的数据接口函数参数也是一样。

  qt里对基本数据格式都进行了封装,提供了如QChar、QBitArray、QByteArray类,使用起来也是很方便。如网络上接受到数据,都是帧流,处理数据时,需要按字节处理(因为通信协议多按字节定义),如上的缓存接口定义就比较合适。

  使用QBuffer+QLinkedList做一个缓存队列就非常容易了。

  下面给出代码:

  FrameStreamManager.cpp

 1 #include "FrameStreamManager.h"
 2 
 3 FrameStreamManager::FrameStreamManager()
 4 {
 5 
 6 }
 7 
 8 FrameStreamManager::~FrameStreamManager()
 9 {
10 
11 }
12 
13 int FrameStreamManager::putFrame(char *in,int length)
14 {
15     int ret;
16     QMutexLocker locker(&mutex);
17 
18     QBuffer *qbuf = new QBuffer();
19     qbuf->open(QBuffer::ReadWrite);
20     ret = qbuf->write(in,length);
21     qbuf->close();
22 
23     list.append(qbuf);
24 
25     return ret;
26 }
27 
28 int FrameStreamManager::getFrame(char *retbuf,int size)
29 {
30     QMutexLocker locker(&mutex);
31     QBuffer *qbuf;
32     int ret=0;
33 
34     if(list.size() > 0)
35     {
36         qbuf = list.takeFirst();
37         qbuf->open(QBuffer::ReadWrite);
38         ret = qbuf->read(retbuf,size);
39         qbuf->close();
40         delete qbuf;
41     }
42 
43     return ret;
44 }
45 
46 int FrameStreamManager::getFrameSize()
47 {
48     return list.size();
49 }
View Code

  FrameStreamManager.h

 1 #ifndef FRAMESTREAMMANAGER_H
 2 #define FRAMESTREAMMANAGER_H
 3 
 4 #include <QLinkedList>
 5 #include <QBuffer>
 6 #include <QByteArray>
 7 #include <QMutexLocker>
 8 #include <QMutex>
 9 
10 class FrameStreamManager
11 {
12 public:
13     FrameStreamManager();
14     ~FrameStreamManager();
15 
16 private:
17     QLinkedList<QBuffer*> list;
18     QMutex mutex;
19 
20 public:
21     int putFrame(char *in,int length);
22     int getFrame(char *rebuf,int size);
23     int getFrameSize(void);
24 };
25 
26 
27 #endif
View Code

  测试文件:

  mainwindow.cpp

  1 #include "mainwindow.h"
  2 #include <QLabel>
  3 #include <QtDebug>
  4 #include <QBuffer>
  5 #include <QPushButton>
  6 
  7 MainWindow::MainWindow(QWidget *parent)
  8     : QMainWindow(parent)
  9 {
 10     this->setFixedSize(320,240);
 11     QLabel *label = new QLabel("hello you are",this);
 12     label->move(0,0);
 13 
 14     QPushButton *btn1 = new QPushButton("put",this);
 15     connect(btn1, SIGNAL(clicked()), this, SLOT(btn1Clicked()));
 16     btn1->move(0,25);
 17 
 18     QPushButton *btn2 = new QPushButton("show",this);
 19     connect(btn2,SIGNAL(clicked()),this,SLOT(btn2Clicked()));
 20     btn2->move(0,60);
 21 
 22     QPushButton *btn3 = new QPushButton("get",this);
 23     connect(btn3,SIGNAL(clicked()),this,SLOT(btn3Clicked()));
 24     btn3->move(0,95);
 25 
 26     for(int i=0;i<512;i++)
 27         defaultbuf[i] = 100;
 28 
 29     memset(retbuf,0,512);
 30 
 31     /*//    int BUFSIZE = 2048;
 32 
 33     //    QBuffer qbuf;
 34     //    qbuf.open(QBuffer::ReadWrite);
 35 
 36     //    char *buf = (char*)malloc(BUFSIZE);
 37     //    for(int i=0;i<BUFSIZE;i++)
 38     //    {
 39     //        buf[i] = 234;
 40     //    }
 41 
 42     //    int ret = qbuf.write(buf,BUFSIZE);
 43     //    qbuf.close();
 44     //    qDebug()<<"ret = "<<ret;
 45 
 46     //    char *retbuf = (char *)malloc(BUFSIZE);
 47     //    memset(retbuf,0,BUFSIZE);
 48     //    qbuf.open(QBuffer::ReadWrite);
 49 
 50     //    ret = qbuf.read(retbuf,BUFSIZE);
 51     //    qDebug()<<"ret = "<<ret;
 52     //    for(int i=0;i<BUFSIZE;i++)
 53     //    {
 54     //        if(retbuf[i] != (char)234)
 55     //        {
 56     //            qDebug()<<"Error at "<<i<<" : "<<retbuf[i];
 57     //        }
 58     //    }
 59     //    qbuf.close();
 60 
 61     //    free(buf);
 62     //    free(retbuf); */
 63 }
 64 
 65 MainWindow::~MainWindow()
 66 {
 67 
 68 }
 69 
 70 void MainWindow::btn1Clicked()
 71 {
 72     qDebug()<<"\nput frame!";
 73 
 74     int len = fsm.putFrame(defaultbuf,512);
 75     if(len != 512)
 76         qDebug()<<"put frame buf";
 77 }
 78 
 79 void MainWindow::btn2Clicked()
 80 {
 81     qDebug()<<"\nshow frame list size!";
 82 
 83     int len = fsm.getFrameSize();
 84     qDebug()<<"Now Frame Size = "<<len;
 85 }
 86 
 87 void MainWindow::btn3Clicked()
 88 {
 89     qDebug()<<"\nget frame and check!";
 90 
 91     int len = fsm.getFrame(retbuf,512);
 92     if(len != 512)
 93         qDebug()<<"get frame returns "<<len;
 94     else
 95     {
 96         for(int i=0;i<512;i++)
 97         {
 98             if(retbuf[i] != 100)
 99                 qDebug()<<" get data error at "<<i<<" : "<<retbuf[i];
100         }
101     }
102 
103     memset(retbuf,0,512);
104 }
View Code

  mainwindow.h

 1 #ifndef MAINWINDOW_H
 2 #define MAINWINDOW_H
 3 
 4 #include <QMainWindow>
 5 #include "FrameStreamManager.h"
 6 
 7 class MainWindow : public QMainWindow
 8 {
 9     Q_OBJECT
10 
11 public:
12     MainWindow(QWidget *parent = 0);
13     ~MainWindow();
14 
15 private slots:
16     void btn1Clicked();
17     void btn2Clicked();
18     void btn3Clicked();
19 
20 private:
21     FrameStreamManager fsm;
22 
23     char defaultbuf[512];
24     char retbuf[512];
25 };
26 
27 #endif // MAINWINDOW_H
View Code

  

  QByteArray也是可以完成同样功能,QByteArray有如下函数,QByteArray & QByteArray::append(const char *str,int len) 和char * QByteArray::data()。就是QByteArray会在返回的char* 数据后自动加‘\0’,但int QByteArray::size()返回来的数是不含'\0',利用size()函数和data()封装一下就可以达到上面QBuffer达到的效果。

  而且使用QByteArray有个好处,QByteArray重载了操作符=,所以FrameStreamManager里的list可以这样定义-->QLinkedList<QByteArray> list。从队列中取数据时可以直接写QByteArray tmp = list.takeFirst();而QBuffer没有重载=操作符,QBuffer tmp = list.takeFirst();这样就写就会直接报错。定义队列时就必须改成上面那样,就需要自己管理内存了。同时,使用QBuffer还需要打开和关闭设备。

  综上,队列中使用QByteArray做存储,封装使用更方便。

       

posted @ 2017-10-12 17:31  kanite  阅读(1529)  评论(0编辑  收藏  举报