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的大小呢?

  • 恩,一旦調用該成員,將會在堆上分配一個指定大小的字符數組。

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