Qt中的和字节流有关的几个Buffer类

QBuffer

这是Qt的一个公有类,manual中说得很清楚:

  • 为QByteArray提供了一个QIODevice的接口,使得该QByteArray可以作为一个random-accessed的普通文件对待。

所以,此处没多少可说的了。一个具体的例子(同样取自Qt的manual):

QImage image;
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG"); // writes image into ba in PNG format

QIODevicePrivateLinearBuffer

私有类 ./src/corelib/io/qiodevice_p.h

一个线性缓冲区,从头部读取数据,从尾部追加数据,也可以在头部插入数据。

class QIODevicePrivateLinearBuffer
{
public:
    QIODevicePrivateLinearBuffer(int);
    ~QIODevicePrivateLinearBuffer();
    void clear();
    int size() const;
    bool isEmpty() const;
    void skip(int n);
    int getChar();
    int read(char* target, int size);
    char* reserve(int size);
    void chop(int size);
    QByteArray readAll();
    int readLine(char* target, int size);
    bool canReadLine() const;
    void ungetChar(char c);
    void ungetBlock(const char* block, int size);
};
  • ungetChar()/ungetBlock() 用来向缓冲区头部追加数据
  • reserve() 用来在尾部申请新的空间,并返回指针
    • 一般需要配合chop() 使用,比如申请10个字节空间,只写入8个字节。需要chop(2)
  • getChar()/read()/readAll()/readLine() 从头部读取数据

QRingBuffer

私有类 ./src/corelib/tools/qringbuffer_p.h

一个环形buffer,在尾部追加数据,从头部读取数据。适合用作IO的缓冲区

class QRingBuffer
{
public:
    inline QRingBuffer(int growth = 4096);
    inline const char *readPointer() const;
    inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const;
    inline void free(int bytes);
    inline char *reserve(int bytes);
    inline void truncate(int pos);
    inline void chop(int bytes);
    inline bool isEmpty() const;
    inline int getChar();
    inline void putChar(char c);

    inline void ungetChar(char c);
    inline int size() const;
    inline void clear();

    inline int indexOf(char c) const;
    inline int indexOf(char c, int maxLength) const;

    inline int read(char *data, int maxLength);
    inline QByteArray read(int maxLength);
    inline QByteArray readAll();
    inline QByteArray read();

    inline void append(const QByteArray &qba);

    inline QByteArray peek(int maxLength) const;
    inline int skip(int length);
    inline int readLine(char *data, int maxLength);
    inline bool canReadLine() const;
};

这个类挺复杂,不过多数成员函数,从名字上能猜个大概。

作为常规使用,我们需要从buffer中读取数据,可以使用:

  • read()/readLine()/readAll()/getChar()

读数比较简单,而如何添加数据,有点不太直观

  • 申请空间 reserve(),可得到一个指针
  • 借助该指针,往空间写入数据 ...
  • 如果申请了10个字节,而只写了8个字节,一定要用 chop() 切掉后面2个。

本来应该可以直接使用 append() 直接追加数据的,但是由于bug的存在,工作得并不好。

另外:ungetChar()/putChar() 分别是在缓冲区头部和尾部放置一个字符。

注:QRingBuffer内部是使用QList<QByteArray>构架的缓冲区。这样一来可以方便地在头部或尾部插入新的QByteArray.

QByteDataBuffer

Qt的私有类 ./src/corelib/tools/qbytedata_p.h

  • this class handles a list of QByteArrays. It is a variant of QRingBuffer that avoid malloc/realloc/memcpy.

class QByteDataBuffer
{
public:
    QByteDataBuffer();
    ~QByteDataBuffer();
    inline void append(QByteDataBuffer& other);
    inline void append(const QByteArray& bd);
    inline void prepend(QByteArray& bd);

    inline QByteArray read();
    inline QByteArray readAll();
    inline QByteArray read(qint64 amount);
    qint64 read(char* dst, qint64 amount);
    inline char getChar();

    inline void clear();
    inline qint64 byteAmount() const;
    inline qint64 bufferCount() const;
    inline bool isEmpty() const;

    inline qint64 sizeNextBlock() const;
    inline QByteArray& operator[](int i);
    inline bool canReadLine() const;
};

接口比 QRingBuffer 清晰很多,也更易用。

QDataBuffer

私有的Qt的模板类:./src/gui/painting/qdatabuffer_p.h

template <typename Type> class QDataBuffer
{
public:
    QDataBuffer(int res);
    ~QDataBuffer();
    inline void reset();

    inline bool isEmpty() const;

    inline int size() const;
    inline Type *data() const;

    inline Type &at(int i);
    inline const Type &at(int i) const;
    inline Type &last();
    inline const Type &last() const;
    inline Type &first();
    inline const Type &first() const;

    inline void add(const Type &t);
    inline void pop_back();
    inline void resize(int size);
    inline void reserve(int size);
    inline void shrink(int size);;

    inline void swap(QDataBuffer<Type> &other);
    inline QDataBuffer &operator<<(const Type &t);
};

模板函数,可返回首尾数据。

  • first()
  • last()

追加和弹出数据,每次一个

  • add()
  • pop_back()

调整缓冲区

  • resize()
  • reserve()
  • shrink()

QTestCharBuffer

一个私有类: src/testlib/qabstracttestlogger_h

这个东西似乎没有什么功能。分配一个buffer,可以改变其大小,可以获取首地址。仅次而已?

struct QTestCharBuffer
{
    inline QTestCharBuffer();
    inline ~QTestCharBuffer();

    inline char *data();
    inline char **buffer();
    inline const char* constData() const;
    inline int size() const;
    inline bool reset(int newSize);
};

类内在栈上分配了一个固定大小512的字符数组:

  • data()/constData() 返回字符数组首地址
  • size() 返回字符数组的大小

前面说字符数组分配在栈上,但是为什么有一个reset()来改变buffer的大小呢?

  • 恩,一旦调用该成员,将会在堆上分配一个指定大小的字符数组。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章