2 回答
TA贡献1891条经验 获得超3个赞
你真的检查err
和完成Len
后c.conn.Read(buf)
吗?
您程序中的主要缺陷(如所示)是您buf
用于搜索数据,而套接字上的读取操作在接收到 1 到 1024 之间的任意数量的字节后可以自由返回成功,并在接收后返回错误0 到 1024 之间的任意字节数。
所以,你必须做两件事:
检查错误;
要在读取操作结束后访问缓冲区开头的实际可用数据,您必须使用数据的实际长度
Len
.
要执行后者,您通常会构造一个新切片:
data := buf[:Len]
然后使用data
变量:
if bytes.Contains(data, []byte("}{")) {
...
}
如果您不这样做,您可能很容易访问缓冲区中的陈旧数据 — 即,上次调用c.conn.Read(buf)
.
如果您再考虑一下这种情况,您会发现没有什么可以保证Read()
您的套接字上的下一次调用会将}{
序列带入缓冲区,并且您必须准备好累积数据:也就是说,
每次调用
Read()
都应将其Len
字节添加到缓冲区中的字节数以供您的代码考虑。这意味着如果第 N 个读取操作未能提供您要查找的数据,则第 (N+1) 个操作必须将其字节放在前一个读取操作的最后一个字节之后;在 Go 中,这通常意味着为下一个读取操作构造另一个切片。
您应该使用当前累积的总字节数来搜索“}{”。
请考虑从本书开始,以掌握网络编程的基础知识(与 Go 相关的细节)。
如您所见,正确处理此任务看起来很复杂。那么为什么不让 Go 自己做缓冲呢?
你可以这样重申你的算法:
读取输入数据直到
}
找到一个字符。积累这些数据。一旦
}
被发现,读取下一个字符,如果是{
,我们已经找到了点,我们感兴趣的问题。否则返回步骤(1)。
这是可行的使用bytes.Buffer
及其方法:
ReadBytes(delim byte)
— 最多读取一个}
字节。ReadByte()
— 用于读取单个字节以检查是否{
跟随。UnreadByte(c byte)
— 用于将字节放回缓冲区,如果它不是{
后续}
.
现在让我们从更一般的角度来看您的问题。您在示例中提供的数据在我看来就像一系列 JSON 对象。那么,您为什么要尝试应用一些低技术方法来查找这些对象之间的边界,而不是仅使用JSON 解码器来立即解码您的数据或至少正确地跳过流中的对象?
TA贡献1804条经验 获得超3个赞
您的代码缺少一些括号等存在问题。这似乎有效:
package main
import (
"bytes"
"fmt"
)
const data = `{"abc":[{"b":5,"bca":14,"xyz":0}]}{"abc":[{"b":7,"hjk":14,"qwe":0}]}`
func main() {
buf := []byte(data)
fmt.Printf("buf = %s\n", string(buf))
if bytes.Contains(buf, []byte("}{")) {
fmt.Printf("I got you\n")
}
}
在您连接的应用程序中接收数据可能存在编码问题,这是一个棘手的问题,我有时会使用打印接收数据的十六进制值来真正查看线路中出现的内容。
编辑 :
尝试像这样打印出接收到的数据:
for _, b := range buf {
fmt.Printf("%X ", b)
}
然后和测试数据对比看看有没有差异,这是你说的唯一可能出错的地方吗?
- 2 回答
- 0 关注
- 280 浏览
添加回答
举报