QDataStream 将错误值写入 QByteArray
QDataStream writing wrong values to QByteArray
我正在 Qt 中编写一个简单的基于 TCP 的网络应用程序,并希望使用 QDataStream
和 QByteArray
通过网络发送数据。问题是,当我将数据放入 QByteArray
时,它们是 "zeroed"。例如(连接到定时器超时信号的 MainWindow
中的一个槽):
void MainWindow::SendPlayer1Data(){
QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h="hello";
s<<h;
qDebug() << "h: " << data;
qDebug() << "block: " << QString(block); // equivalent to s >> h on receiving end
qDebug() << "block[0]: " << int(block[0]);
}
h: "hello"
block: ""
block[0]: 0
一开始我收到了一次"hello"
,但之后我只收到了""
。 qint32
也是如此。客户端和服务器都显示 QByteArray
大小为 14 字节,因此 QDataStream
将数据写入该数组,但它使它们成为 0
(当我使用 [= 时显示 ""
23=] 然后使用 qDebug() << h
)
这里的问题是将 QString
直接写入需要 QByteArray
的流,请考虑以下
QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
s << h;
qDebug() << block;
输出
"\x00\x00\x00\n\x00h\x00""e\x00l\x00l\x00o"
所以数据就在那里,只是不像人们所期望的那样。解决此问题的最简单方法是从使用 UTF8(或您选择的其他编码)编码的字符串创建 QByteArray
。这可以轻松地即时完成,
QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
QByteArray data(h.toUtf8(), 5);
s << data;
qDebug() << block;
输出
"\x00\x00\x00\x05hello"
因为当这个 QByteArray
通过 QDataStream
发送时,数组的长度和 3 个 NULL
字符被前置 - NULL
字符在那里以防万一缓冲区大于相对较小的 5
(您可以通过传递一个更大的值来为自己测试 - 256 的小系数最能说明问题 - 作为 QByteArray
构造函数中的第二个参数,因为这是缓冲区长度)。但是,如果您尝试从 NULL
-开始的 QByteArray
显式构造 QString
(如 s >> h
所做的那样),它将创建一个空字符串。要纠正这个问题,您可以使用 QByteArray::remove()
删除前 4
个字节,例如
QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
QByteArray data(h.toUtf8());
s << data;
qDebug() << QString::fromUtf8(block.remove(0, 4));
输出
"hello"
完整示例
#include <qbytearray.h>
#include <qdatastream.h>
#include <qdebug.h>
int main() {
QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
QByteArray data(h.toUtf8());
s << data;
qDebug() << QString::fromUtf8(block.remove(0, 4));
}
好的,我已经弄明白了。
问题不在于 QByteArray
或套接字,因为正如 @William Miller
提到的那样,数据就在那里。
问题出在客户端的 QDataStream
- 我决定在每次调用负责接收数据的插槽时创建一个新的 QDataStream
对象。这样我就可以轻松地将数据打包到 QByteArray
中,每次都发送和接收。
接收客户端函数:
void ClientTcpHelper::ReceivePacket(){
if(socket.waitForReadyRead(20)){
//qDebug()<<"Packet: "<<socket.peek(30)<<endl;
qDebug()<<"Receiving packet!"<<endl;
Data=socket.readAll();
emit DataReceived();
}
else{
//qDebug()<<"Failed to receive packet!"<<endl;
}}
并将数据解包到变量:
void ClientTcpHelper::UnpackData(){
stream=new QDataStream (&this->Data,QIODevice::OpenModeFlag::ReadWrite);
*stream>>h>>a>>b;
Data.clear();
delete stream;}
h,a 和 b 是 a class.
的成员
不幸的是,我无法解释为什么 QDataStream
每次都需要销毁,以便从一开始就按照我的意愿处理数据。
我正在 Qt 中编写一个简单的基于 TCP 的网络应用程序,并希望使用 QDataStream
和 QByteArray
通过网络发送数据。问题是,当我将数据放入 QByteArray
时,它们是 "zeroed"。例如(连接到定时器超时信号的 MainWindow
中的一个槽):
void MainWindow::SendPlayer1Data(){
QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h="hello";
s<<h;
qDebug() << "h: " << data;
qDebug() << "block: " << QString(block); // equivalent to s >> h on receiving end
qDebug() << "block[0]: " << int(block[0]);
}
h: "hello"
block: ""
block[0]: 0
一开始我收到了一次"hello"
,但之后我只收到了""
。 qint32
也是如此。客户端和服务器都显示 QByteArray
大小为 14 字节,因此 QDataStream
将数据写入该数组,但它使它们成为 0
(当我使用 [= 时显示 ""
23=] 然后使用 qDebug() << h
)
这里的问题是将 QString
直接写入需要 QByteArray
的流,请考虑以下
QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
s << h;
qDebug() << block;
输出
"\x00\x00\x00\n\x00h\x00""e\x00l\x00l\x00o"
所以数据就在那里,只是不像人们所期望的那样。解决此问题的最简单方法是从使用 UTF8(或您选择的其他编码)编码的字符串创建 QByteArray
。这可以轻松地即时完成,
QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
QByteArray data(h.toUtf8(), 5);
s << data;
qDebug() << block;
输出
"\x00\x00\x00\x05hello"
因为当这个 QByteArray
通过 QDataStream
发送时,数组的长度和 3 个 NULL
字符被前置 - NULL
字符在那里以防万一缓冲区大于相对较小的 5
(您可以通过传递一个更大的值来为自己测试 - 256 的小系数最能说明问题 - 作为 QByteArray
构造函数中的第二个参数,因为这是缓冲区长度)。但是,如果您尝试从 NULL
-开始的 QByteArray
显式构造 QString
(如 s >> h
所做的那样),它将创建一个空字符串。要纠正这个问题,您可以使用 QByteArray::remove()
删除前 4
个字节,例如
QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
QByteArray data(h.toUtf8());
s << data;
qDebug() << QString::fromUtf8(block.remove(0, 4));
输出
"hello"
完整示例
#include <qbytearray.h>
#include <qdatastream.h>
#include <qdebug.h>
int main() {
QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
QByteArray data(h.toUtf8());
s << data;
qDebug() << QString::fromUtf8(block.remove(0, 4));
}
好的,我已经弄明白了。
问题不在于 QByteArray
或套接字,因为正如 @William Miller
提到的那样,数据就在那里。
问题出在客户端的 QDataStream
- 我决定在每次调用负责接收数据的插槽时创建一个新的 QDataStream
对象。这样我就可以轻松地将数据打包到 QByteArray
中,每次都发送和接收。
接收客户端函数:
void ClientTcpHelper::ReceivePacket(){
if(socket.waitForReadyRead(20)){
//qDebug()<<"Packet: "<<socket.peek(30)<<endl;
qDebug()<<"Receiving packet!"<<endl;
Data=socket.readAll();
emit DataReceived();
}
else{
//qDebug()<<"Failed to receive packet!"<<endl;
}}
并将数据解包到变量:
void ClientTcpHelper::UnpackData(){
stream=new QDataStream (&this->Data,QIODevice::OpenModeFlag::ReadWrite);
*stream>>h>>a>>b;
Data.clear();
delete stream;}
h,a 和 b 是 a class.
的成员不幸的是,我无法解释为什么 QDataStream
每次都需要销毁,以便从一开始就按照我的意愿处理数据。