2008-10-10 36 views
5

Tìm kiếm chuỗi trong chuỗi được hỗ trợ rất tốt trong .NET nhưng bạn làm gì khi dữ liệu bạn cần tìm kiếm không phải là chuỗi?Tìm kiếm byte []

Tôi có dữ liệu nhị phân đến các khối thông thường thông qua NetworkStream. Các gói là nhị phân nhưng tất cả chúng đều bắt đầu bằng một chuỗi ký tự các byte. Tôi tích lũy các khối thành một bộ đệm lớn hơn và tìm chữ ký bắt đầu của gói.

Điều tôi thực sự tìm kiếm là byte[] tương đương với phương pháp String.IndexOf(ss). Tôi có một cảm giác khó chịu, tôi sẽ phải thực hiện điều này bản thân mình với một vòng lặp và một máy nhà nước.

Mọi đề xuất? Cho bạn!


Như đã đề xuất, Array.IndexOf (byte) sẽ ít nhất là lưu cho tôi một vòng lặp rõ ràng. Kể từ khi đăng bài, nó xảy ra với tôi để tìm byte chữ ký đầu tiên, sau đó thăm dò trước cho một trận đấu mà byte chữ ký cuối cùng nên, sau đó nếu cả hai trận đấu thử một so sánh brute-force cho phần còn lại của chuỗi. Cách tiếp cận này có lợi thế là từ chối các kết quả phù hợp với giá rẻ và cho phép tôi từ chối một cách rẻ tiền khi tôi có một chữ ký một phần đang chờ xử lý một đoạn khác.

Google tiết lộ rằng kế hoạch tuyệt vời ở trên là một trường hợp thoái hóa của thuật toán "KMP" hoặc Knuth-Morris-Pratt. Về mặt tươi sáng, nếu Knuth đặt tên của anh ta trên đó, nó có lẽ là sét bị sét, về mặt nhược điểm, tại sao nó lại bất cứ khi nào tôi có một ý tưởng hay Donald Knuth nghĩ về nó 25 năm trước?

Vì tôi không thể trao điểm cho Donald Knuth Tôi đoán họ sẽ đến Nelson.

Trả lời

3

Bạn có thể sử dụng Array.IndexOf để tìm một byte đơn.

Tuy nhiên, tôi sẽ cảnh báo bạn rằng một số dữ liệu hợp lệ có thể vô tình là chữ ký của bạn và hoàn toàn xóa ứng dụng của bạn. Một giải pháp tốt hơn theo ý kiến ​​của tôi sẽ là luôn luôn gửi một số nguyên bốn byte có chứa kích thước của gói tin. Sau đó đọc nhiều byte để xóa bộ đệm của gói đó.

Nếu bạn đang sử dụng giao thức TCP nó là hoàn toàn có thể chấp nhận để kick một khách hàng nếu họ nói dối về kích thước gói tin hoặc yêu cầu một lượng ngu ngốc bộ nhớ :)

+0

Tôi không thể viết giao thức, tôi đang nói đến phần cứng cũ. Tôi có thể viết phiên bản tiếp theo và tôi đã chỉ định chính xác đề xuất của bạn. –

0

Bạn có thể sử dụng mã không được quản lý/không an toàn? Nếu vậy tôi có lẽ sẽ đề nghị xem xét sử dụng số học con trỏ để tìm kiếm mảng byte của bạn. Đó là cách dây có hiệu quả. Bạn có thể làm tương tự.

một giải pháp khác có thể là sử dụng từ điển để lưu trữ dữ liệu gói của bạn. Có chìa khóa là chữ ký của bạn. Sau đó, nó khá nhanh chóng và dễ dàng để tìm thấy nó. Một số cách để có byte như một khóa, chẳng hạn như base64string, một wrapper simepl (sử dụng KeyedCollection nếu bạn làm điều này), v.v.

+0

Mã không được quản lý thực sự là PITA vì chúng ta có môi trường 32/64 hỗn hợp. Thật ngạc nhiên là rắc rối ít hơn nhiều đối với mã được quản lý thuần túy. Catch-22: Tôi cần chữ ký để phân tích luồng thành các gói. –

2

Thuật toán nhanh nhất để tìm mẫu trong chuỗi byte và chuỗi mà tôi đã sử dụng là Boyer-Moore và đơn giản Boyer-Moore (hữu ích khi mẫu có khác biệt đáng kể so với văn bản đang được tìm kiếm). Tôi đã sử dụng điều này để triển khai trình phân tích cú pháp nhanh trong Java. Các code có thể dễ dàng được chuyển đến .Net (giấy phép là LGPL).

Các vấn đề liên quan