在.NET中搜索字符串中的字符串非常受支持,但是当您需要搜索的数据不是字符串时,您会怎么做?
我有二进制数据通过NetworkStream以常规块的形式到达。数据包是二进制的,但它们都以签名字节序列开头。我将块累积到一个更大的缓冲区中,并寻找数据包开始签名。
我真正想要的是与byte[]
方法等效的String.IndexOf(ss)
。我有一种讨厌的感觉,我将不得不用循环和状态机来实现这一点。
有什么建议吗?给你!
正如所建议的,Array.IndexOf(byte)至少会为我保存一个显式循环。自发布以来,我发现找到第一个签名字节,然后向前探测最后一个签名字节应该匹配的匹配,然后如果它们都匹配,则尝试对字符串的其余部分进行强力比较。这种方法的优点是可以廉价地拒绝错误匹配,并允许我在部分签名等待另一个块时便宜地拒绝。
谷歌透露,上述出色的计划是“KMP”或Knuth-Morris-Pratt算法的退化案例。如果Knuth把自己的名字放在它上面那么光明的一面,它可能是闪电般的闪电,在不利方面,为什么每当我有一个好主意时唐纳德·克努特在25年前都会想到它?由于我无法将分数奖励给Donald Knuth,我猜他们会去尼尔森。
答案 0 :(得分:3)
您可以使用Array.IndexOf查找单个字节。
但是,我会提醒您,某些有效数据可能会意外地成为您的签名并完全放弃您的申请。在我看来,更好的解决方案是始终发送一个包含数据包大小的四字节整数。然后读取多个字节以清除该数据包的缓冲区。
如果您正在使用TCP,如果客户端因数据包大小或请求愚蠢的内存量而将客户端关闭是完全可以接受的:)
答案 1 :(得分:2)
在我使用的字节数组和字符串中查找模式的最快算法是Boyer-Moore和简单的Boyer-Moore(当模式与正在搜索的文本明显不同时很有用)。我用它在Java中实现了一个快速的mime解析器。 code可以很容易地移植到.Net(许可证是LGPL)。
答案 2 :(得分:0)
您可以使用非托管/不安全的代码吗?如果是这样,我可能会建议使用指针算法来搜索你的字节数组。这就是字符串的有效性。你可以做类似的事。
另一种解决方案可能是使用字典来存储您的数据包数据。把密钥作为你的签名。然后它相当快速,容易找到它。将字节作为键的几种方法,例如base64string,simepl包装器(如果你这样做,使用KeyedCollection)等。