我有一个很奇怪的问题,使用QDataStream
,或者至少对我来说很奇怪,因为我根本不了解这种行为。
当然,我的问题来自一个大项目,但是我设法用一个最小的例子重现了这种奇怪的行为,我将在下面进行描述。
我有两节课
Reader
和Parser
。 Reader
通过QTcpSocket
读取数据,将每个接收到的数据块打包到QByteArray
中,然后通过Qt信号将该数组发送到Parser
。Parser
将所有接收到的数据块写入其自己的QDataStream
,然后将解析该流中的数据包。当
Parser
将数据从接收到的QByteArray
写入其QDataStream
时,就会出现问题。 QDataStream::writeRawData
的返回值正确返回写入的字节数,但是QDataStream::atEnd
返回true
,而QDataStream::device.bytesAvailable
返回零。为什么? 数据
QDataStream::writeRawData
声称写在哪里? 您可以在这篇文章的和找到代码。
环境:Windows 7 Enterprise SP1 64位上的 Qt 5.9.1(MSVC 2015,32/64位)
Reader.h
#ifndef READER_H
#define READER_H
#include <QAbstractSocket>
#include <QByteArray>
#include <QDataStream>
#include <QHostAddress>
#include <QObject>
class Reader : public QObject
{
Q_OBJECT
public:
Reader(const QHostAddress ip, quint16 port);
virtual ~Reader();
signals:
void signalNewData(const QByteArray data);
private slots:
void slotOnReadyRead();
private:
QAbstractSocket *mSocket;
QDataStream mStream;
};
#endif // READER_H
Reader.cpp
#include "reader.h"
#include <QTcpSocket>
Reader::Reader(const QHostAddress ip, quint16 port)
: mSocket(new QTcpSocket(this))
, mStream()
{
mStream.setDevice(mSocket);
mStream.setVersion(QDataStream::Qt_5_9);
mStream.setByteOrder(QDataStream::LittleEndian);
connect(mSocket, &QIODevice::readyRead, this, &Reader::slotOnReadyRead);
mSocket->connectToHost(ip, port, QIODevice::ReadOnly);
}
Reader::~Reader()
{
mSocket->disconnectFromHost();
delete mSocket;
mSocket = nullptr;
}
void Reader::slotOnReadyRead()
{
mStream.startTransaction();
quint64 availableBytesForReading = mStream.device()->bytesAvailable();
QByteArray binaryDataBlock;
char *tmp = new char[availableBytesForReading];
mStream.readRawData(tmp, availableBytesForReading);
binaryDataBlock.append(tmp, availableBytesForReading);
delete[] tmp;
tmp = nullptr;
if (mStream.commitTransaction())
{
emit signalNewData(binaryDataBlock);
}
}
Parser.h
#ifndef PARSER_H
#define PARSER_H
#include <QByteArray>
#include <QDataStream>
#include <QObject>
class Parser : public QObject
{
Q_OBJECT
public:
Parser();
public slots:
void slotOnNewData(const QByteArray data);
private:
QDataStream mStream;
};
#endif // PARSER_H
Parser.cpp
#include "parser.h"
#include <QDebug>
Parser::Parser()
: mStream(new QByteArray(), QIODevice::ReadWrite)
{
mStream.setVersion(QDataStream::Qt_5_9);
mStream.setByteOrder(QDataStream::LittleEndian);
}
void Parser::slotOnNewData(const QByteArray data)
{
const char *tmp = data.constData();
int numberOfBytesWritten = mStream.writeRawData(tmp, data.length());
qDebug() << "numberOfBytesWritten:" << numberOfBytesWritten << endl;
qDebug() << "QDataStream::status():" << mStream.status() << endl;
qDebug() << "QDataStream::atEnd():" << mStream.atEnd() << endl;
qDebug() << "QDataStream::device.bytesAvailable():" << mStream.device()->bytesAvailable() << endl;
}
main.cpp
#include <QCoreApplication>
#include "reader.h"
#include "parser.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Reader *reader = new Reader(QHostAddress("<insert IP>"), <insertPort>);
Parser *parser = new Parser();
QObject::connect(&a, &QCoreApplication::aboutToQuit, reader, &QObject::deleteLater);
QObject::connect(&a, &QCoreApplication::aboutToQuit, parser, &QObject::deleteLater);
QObject::connect(reader, &Reader::signalNewData, parser, &Parser::slotOnNewData);
return a.exec();
}
delete.pro 是的,我将最小示例项目称为“delete”:'D
QT += core network
QT -= gui
CONFIG += c++11
TARGET = delete
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp \
reader.cpp \
parser.cpp
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
HEADERS += \
reader.h \
parser.h
最佳答案
问题不在于没有数据,而是您的当前位置在数据的末尾。使用device()
检索用于包装QBuffer
的QByteArray
并重置该对象的位置。
mStream.device()->reset()
关于c++ - 调用QDataStream::writeRawData后,QDataStream为空,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55146979/