質問

文字列内の文字列の検索は.NETで非常によくサポートされていますが、検索する必要があるデータが文字列ではない場合はどうしますか?

NetworkStreamを介して通常のチャンクで到着するバイナリデータがあります。パケットはバイナリですが、すべてバイトの署名シーケンスで始まります。チャンクをより大きなバッファーに蓄積し、パケットの開始署名を探します。

本当に探しているのは、 String.IndexOf(ss)メソッドに相当する byte [] です。ループとステートマシンを使用してこれを自分で実装しなければならないという不快な気持ちがあります。

提案はありますか?あなたに!


提案されているように、Array.IndexOf(byte)は少なくとも明示的なループを保存します。投稿してから、最初の署名バイトを見つけて、最後の署名バイトがあるはずの一致を探し、それらの両方が一致する場合、残りの文字列についてブルートフォース比較を試みます。このアプローチには、偽の一致を安価に拒否し、別のチャンクを保留している部分署名がある場合に安価に拒否できるという利点があります。

Googleは、上記の素晴らしい計画が「KMP」の退化した事例であることを明らかにしています。またはKnuth-Morris-Prattアルゴリズム。明るい面では、Knuthが彼の名前を付けた場合、おそらく稲妻に油を塗ったでしょう。

ドナルドクヌースにポイントを授与できないため、ネルソンに行くと思います。

役に立ちましたか?

解決

Array.IndexOfを使用して1バイトを検索できます。

ただし、いくつかの有効なデータが誤って署名になり、アプリケーションが完全に破棄される可能性があることに注意してください。私の意見では、より良い解決策は、パケットのサイズを含む4バイト整数を常に送信することです。次に、そのパケットのバッファをクリアするために、その多くのバイトを読み込みます。

TCPを使用している場合、クライアントがパケットサイズについてうそをついていたり、愚かな量のメモリを要求していれば、クライアントをキックオフすることは完全に受け入れられます:

他のヒント

使用したバイト配列および文字列内のパターンを見つけるための最速のアルゴリズムは、 Boyer-Mooreです。 および単純なボイヤームーア(パターンが検索対象のテキストと大きく異なる場合に便利です)。これを使用して、Javaで高速MIMEパーサーを実装しました。 コード .Netに簡単に移植できます(ライセンスはLGPLです)。

アンマネージ/アンセーフコードを使用できますか?もしそうなら、私はおそらくあなたのバイト配列を検索するためにポインタ演算を使用することを検討することをお勧めします。それが文字列の効果的な方法です。同様のことができます。

別の解決策は、辞書を使用してパケットデータを保存することです。キーを署名にします。その後、かなり高速で簡単に見つけることができます。 base64string、simeplラッパー(これを行う場合はKeyedCollectionを使用)など、バイトをキーとして使用するいくつかの方法。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top