gpt4 book ai didi

c++ - 调用 QDataStream::writeRawData 后 QDataStream 为空

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:03:29 26 4
gpt4 key购买 nike

我有一个相当奇怪的问题,使用 QDataStream,或者至少对我来说很奇怪,因为我根本不理解这种行为。

当然,我的问题来自一个大项目,但我设法用一个最小的例子重现了这种奇怪的行为,我现在将对此进行描述。

我有两个类(class)

  1. 二进制数据阅读器 Reader
  2. 二进制数据解析器解析器

Reader 通过 QTcpSocket 读取数据,将每个接收到的数据 block 打包到 QByteArray 中,并通过 Qt 信号将该数组发送到 解析器

解析器将所有接收到的数据 block 写入它自己的QDataStream,然后解析来自该流的数据包。

Parser 将接收到的 QByteArray 中的数据写入其 QDataStream 时,问题就出现了。 QDataStream::writeRawData 的返回值正确地返回写入的字节数,但是 QDataStream::atEnd 返回 trueQDataStream::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);
}
}

解析器.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

解析器.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 是的,我将我的最小示例项目称为“删除”:'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() 检索用于包装您的 QByteArrayQBuffer 并重置该对象的位置。

mStream.device()->reset()

关于c++ - 调用 QDataStream::writeRawData 后 QDataStream 为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55146979/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com