2013-02-12 55 views
13

Tôi cần phải tìm kiếm một chuỗi, khoảng 13 ký tự, trong một nhóm các tệp văn bản sử dụng C#. Số lượng tệp văn bản đang thay đổi và có thể nằm trong khoảng từ 100-1000. Kích thước của các tệp có thể nằm trong khoảng từ 1KB đến 10MB.Cách nhanh hơn để tìm kiếm một chuỗi trong các tệp văn bản

Tôi đã thử cách ngây thơ để mở mỗi tệp, đọc từng dòng một và xem chuỗi có tồn tại không (sử dụng index.of), nhưng quá chậm. Tôi cũng đã thử sử dụng thuật toán Boyer-Moore, đã cải thiện thời gian, 5 giây, nhưng vẫn cảm thấy chậm.

Bất kỳ ý tưởng nào về cách tăng tốc tìm kiếm?

+2

Sự chậm lại của bạn có thể xuất phát từ việc đọc từng dòng tệp. Đọc một tập tin cùng một lúc vào bộ nhớ và tìm kiếm. – dda

+0

http://stackoverflow.com/questions/4289353/fastest-way-to-search-ascii-files-in-c-sharp-for-simple-keywords – Ofiris

+0

Bạn có cần thực hiện tìm kiếm trên cùng một tệp nhiều lần không? – user626528

Trả lời

3

Bạn nên cân nhắc việc sử dụng tìm kiếm tệp Hệ điều hành có nội dung. Hãy xem Microsoft Windows Search 3.x SDK

Hoặc bạn có thể sử dụng PLINQ để tìm kiếm trong mảng tệp. Xem liên kết này:

File Content and Directory Search using Directory.GetFiles and PLINQ

+1

Không downvoting, nhưng tôi có thể hiểu nó: bạn chỉ cần thực hiện một giải pháp ngu ngốc (về cơ bản IndexOf) song song với PLINQ, không làm cho nó trở thành giải pháp tốt - về cơ bản bạn chỉ cần ném thêm phần cứng vào nó, nhanh hơn. Nó giống như nói cho anh chàng để đọc và xử lý các tập tin của mình trong nhiều chủ đề. Sử dụng boyer-moore như anh ta gợi ý là tốt hơn nhiều so với điều này. Ngoài ra tôi không chắc liệu MS Search có hỗ trợ tùy chỉnh mã thông báo hay không, điều này có vẻ là một yêu cầu. Vì vậy, theo ý kiến ​​của tôi là một chuyên gia tìm kiếm, có nhiều câu trả lời hay hơn ở đây so với bạn. Xin lỗi ... Tôi đánh giá cao ý định tốt. – atlaste

+0

Rực rỡ! PLINQ là faaast! và chỉ là một vài dòng! tôi đã sử dụng ReadAllText thay vào đó và đây là nhanh nhất. –

3

Hai tùy chọn tôi suy nghĩ:

Đọc tập tin văn bản của bạn trong bộ nhớ và chỉ cần tìm kiếm trên toàn bộ chuỗi cùng một lúc.

Nếu điều đó chứng tỏ là quá chậm hoặc quá thiếu bộ nhớ, hãy sử dụng trình chỉ mục như Apache Lucene. Có một SDK thoải mái và dễ dàng cho rằng sẵn sàng cho .NET, được gọi là Lucene.net

Dưới đây là một giới thiệu nhỏ cho nó: http://www.codeproject.com/Articles/29755/Introducing-Lucene-Net

1

Nếu máy tính của bạn có thể xử lý nó thử tải tất cả các file văn bản vào bộ nhớ (sử dụng technique shown here và sau đó đánh giá văn bản trong bộ nhớ

Nếu bạn không thể xử lý tất cả các tệp cùng một lúc, hãy thực hiện việc này cho các tệp nhỏ nhất. để giảm thiểu điều đó càng nhiều càng tốt.

8

Tùy thuộc vào ho w nhiều lần bạn muốn làm 'tìm kiếm', bạn muốn sử dụng một công cụ tìm kiếm hay không. Nếu bạn muốn tìm kiếm nhiều lần, hãy sử dụng công cụ tìm kiếm, nếu không: không. Tôi sẽ mô tả cách triển khai cả hai kịch bản ở đây.

Khi sử dụng công cụ tìm kiếm: Có vẻ như bạn đang tìm kiếm các bản chất, có nghĩa là bạn nên lập chỉ mục các tệp của mình bằng cách sử dụng công cụ tìm kiếm ưa thích của mình, tốt nhất là bạn có thể tùy chỉnh (lucene, terrier, v.v.). Kỹ thuật bạn cần ở đây là lập chỉ mục trigram, nghĩa là: tất cả các kết hợp 3 ký tự phải được lập chỉ mục. F.ex .: 'foobar' sẽ tạo ra 'foo', 'oob', 'oba' và 'bar'. Khi tìm kiếm, bạn muốn thực hiện tương tự với truy vấn của mình và đưa ra một truy vấn công cụ tìm kiếm với AND của tất cả các trigram này. (Điều đó sẽ chạy một hợp nhất tham gia vào danh sách gửi bài từ các tài liệu, mà sẽ trả lại ID của họ hoặc bất cứ điều gì bạn đưa vào danh sách gửi bài).

Hoặc, bạn có thể triển khai các mảng hậu tố và lập chỉ mục các tệp của mình một lần. Điều này sẽ cung cấp cho một chút linh hoạt hơn nếu bạn muốn tìm kiếm ngắn (1-2 char) chất nền, nhưng về mặt chỉ số là khó khăn hơn để duy trì. (Có một số nghiên cứu tại CWI/Amsterdam cho mảng hậu tố lập chỉ mục nhanh)

Khi bạn muốn tìm kiếm chỉ một vài lần, thuật toán sử dụng là Boyer-Moore (tôi thường sử dụng Boyer-moore-sunday như mô tả trong [Graham A. Stephen, String Search]) hoặc DFA được biên soạn (bạn có thể xây dựng chúng từ một NFA, dễ dàng hơn để tạo). Tuy nhiên, điều đó sẽ chỉ cung cấp cho bạn một tốc độ tăng nhỏ, vì lý do đơn giản là đĩa IO có lẽ là nút cổ chai của bạn và so sánh một loạt các byte mà bạn cần giải mã anyways là khá nhanh.

Cải tiến lớn nhất bạn có thể thực hiện là không đọc từng dòng tệp của bạn, nhưng theo khối. Bạn nên định cấu hình NTFS để sử dụng kích thước khối 64 KB nếu bạn có thể đọc các tệp với số lượng 64 KB - suy nghĩ 4 MB trở lên trong một lần đọc. Tôi thậm chí còn đề nghị sử dụng IO không đồng bộ để bạn có thể đọc và xử lý (đọc dữ liệu trước đó) cùng một lúc. Nếu bạn làm điều đó một cách chính xác, điều đó đã cung cấp cho bạn việc triển khai phân chia thứ hai cho 10 MB trên phần cứng hiện đại nhất.

Cuối cùng nhưng không kém phần quan trọng, một mẹo nhỏ gọn được sử dụng trong suốt quá trình truy xuất thông tin cũng là để nén dữ liệu của bạn bằng thuật toán nén nhanh. Kể từ khi đĩa IO là chậm hơn so với bộ nhớ/CPU hoạt động, điều này có lẽ sẽ giúp đỡ là tốt. Máy nén Snappy của Google là một ví dụ điển hình về thuật toán nén nhanh.

1

Bạn có thể sử dụng dịch vụ lập chỉ mục của Microsoft để tìm kiếm tài liệu trong các thư mục mà bạn sẽ thêm vào danh mục. Here là một bài viết rất hay mà bạn có thể sử dụng để tìm kiếm các tệp văn bản của mình

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