利用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 }
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
测试文件:
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 }
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
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做存储,封装使用更方便。