我正在尝试将数据从Qt发送到R.我是QtNetwork模块的新手,对整个Qt来说相对较新。因此,我也试图弄清楚QIODevice如何为读写目的编码数据。
如果我运行Fortune Server Example并使用R中的以下代码连接到它:
connection <- socketConnection(host="localhost", port=50743, open="rb", timeout=10)
readBin(connection, what="raw", n = 1000)
返回以下原始十六进制向量
00 00 00 56 00 59 00 6f 00 75 00 20 00 77 00 69 00 6c 00 6c 00 20 00 66 00 65 00 65 00 6c 00 20 00 68 00 75 00 6e 00 67 00 72 00 79 00 20 00 61 00 67 00 61 00 69 00 6e 00 20 00 69 00 6e 00 20 00 61 00 6e 00 6f 00 74 00 68 00 65 00 72 00 20 00 68 00 6f 00 75 00 72 00 2e
删除前五个字节和所有剩余的空字符并转换为char我得到:
"You will feel hungry again in another hour."
所以我想知道的是,所有不属于财富的角色来自哪里?第四个字节似乎是从第六个字节到结尾的消息的字节长度,其余的“非幸运”字符都是空的。
我读到QByteArray用空字符终止每个字节,QByteArray在被QTcpSocket写入之前转换为QBuffer,这是发生了什么? QBuffer添加消息的长度(但是其他四个字节中的哪一个)和QByteArray的每个第二个字节都是空字符?此外,最后一个字节不为空(readBin操作是否消耗它/ readBin如何知道消息的结束位置)?
这是将数据写入套接字的唯一方法吗?如果我想传输double类型的值,我是否必须将它们转换为QByteArray以这种方式传输它们?是不是有一些通过套接字传输数据的非文本方式?
任何启蒙都会非常感激!
编辑:
谢谢你的回答!为了完整起见,这里是你如何解码R
中的字符串connection <- socketConnection(host="localhost", port=50743, open="rb", timeout=10)
# Read first 32 bits, which contains the size of the string in bytes
len.raw <- readBin(connection, what="raw", n = 4)
# convert to integer
len <- strtoi(paste(c("0x",len.raw),collapse=""))
# Read raw message
msg.raw <- readBin(connection, what="raw", n = len)
# convert to char using UTF-16BE
msg <- iconv(list(msg.raw),from="UTF-16BE")
close(connection)
cat(msg)
答案 0 :(得分:0)
如果您看一下Fortune Server示例的实现方式,您可以看到它使用QDataStream
来通过套接字序列化财富(QString
):
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << fortunes.at(qrand() % fortunes.size());
所以,问题简化为“QDataStream
序列化QString
怎么样?”,这在serializing Qt data types的文档页面中得到了广泛的回答。您可以看到QString
的序列化如下所示:
- 如果字符串为null:0xFFFFFFFF(quint32)
- 否则:以字节为单位的字符串长度(quint32),后跟UTF-16中的数据
这正是你在问题中看到的。前四个字节是以字节为单位的字符串长度,由于使用UTF-16编码,后面会出现“空值”。
这是将数据写入套接字的唯一方法吗?如果我想传输double类型的值,我是否必须将它们转换为QByteArray以这种方式传输它们?是不是有一些通过套接字传输数据的非文本方式?
您可以使用自己喜欢的任何serialization format。 QDataStream
在Qt中被广泛使用,因为它支持大多数开箱即用的Qt数据类型。这与使用QByteArray
无关,您可以让QDataStream
直接写入套接字。实际上,QDataStream
是二进制格式(非文本),如您所见。如果需要文本的人类可读格式,您可以使用JSON。
但是如果您的目标是使用QDataStream
将数据从Qt发送到R,则必须为R编写QDataStream
解串器。我建议使用一些具有实现功能的通用数据序列化C ++和R(代替重新发明轮子)。我相信JSON符合这个标准,如果你想使用二进制格式,msgpack可能对你很有意思,因为它支持很多编程语言(包括R和C ++)。