2010-10-21 34 views
9

Tôi đang làm việc với tệp gia tăng khoảng 1 GB và tôi muốn tìm kiếm một mẫu cụ thể. Hiện tại tôi đang sử dụng các biểu thức chính quy của Java, bạn có biết làm cách nào để làm điều này nhanh hơn không?Cách tìm kiếm mẫu có thể hoạt động nhanh hơn?

+2

Âm thanh như thế này phải là I/O-bound. Chương trình chỉ đọc và loại bỏ nội dung của tệp chạy nhanh như thế nào? Biểu thức chính quy sẽ có thể tiếp cận cùng một tốc độ, hoặc nếu không có điều gì đó sai (như đệm). Nếu chỉ đọc tệp quá chậm cho mục đích của bạn, thì bạn cần phải xem xét một cách tiếp cận khác (tức là thảo luận về Lucene bên dưới). –

+0

Bạn có thể hiển thị mẫu và một chút của tệp không. Có thể biểu hiện chậm vì nó không tối ưu. Chương trình của bạn có tải toàn bộ nội dung của tệp vào chuỗi để chạy regex không? Đó là phần chậm? –

Trả lời

7

Về cơ bản những gì bạn cần là một máy trạng thái có thể xử lý luồng. Luồng này bị ràng buộc vào tệp ... Mỗi lần tệp phát triển, bạn đọc những gì đã được nối thêm vào nó (giống như lệnh linux đuôi nối thêm vào đầu ra tiêu chuẩn các dòng được thêm vào tệp).

Nếu bạn cần dừng/khởi động lại máy phân tích, bạn có thể chỉ lưu trữ vị trí bắt đầu ở đâu đó (có thể phụ thuộc vào cửa sổ bạn cần cho mẫu phù hợp) và khởi động lại từ đó. Hoặc bạn có thể khởi động lại từ đầu.

Đó là phần "tăng tệp" của sự cố.

Để có cách tốt nhất để xử lý nội dung, nó phụ thuộc vào những gì bạn thực sự cần, loại dữ liệu và mẫu bạn muốn áp dụng. Cụm từ thông dụng có thể là giải pháp tốt nhất: linh hoạt, nhanh chóng và tương đối thuận tiện.

Từ hiểu biết của tôi, Lucene sẽ tốt nếu bạn muốn thực hiện tìm kiếm đối sánh tài liệu cho một số nội dung ngôn ngữ tự nhiên. Đây sẽ là lựa chọn không phù hợp với tất cả các ngày hoặc tất cả các dòng có thuộc tính cụ thể. Cũng bởi vì Lucene đầu tiên tạo ra một chỉ mục của tài liệu ... Điều này sẽ chỉ giúp cho việc xử lý thực sự nặng nề khi lập chỉ mục ở nơi đầu tiên mất thời gian.

8

Âm thanh như một công việc cho Apache Lucene.

Bạn có thể sẽ phải suy nghĩ lại chiến lược tìm kiếm của mình, nhưng thư viện này được tạo để thực hiện những việc như thế này và thêm các chỉ mục theo từng bước.

Nó hoạt động bằng cách xây dựng chỉ mục ngược của dữ liệu của bạn (tài liệu trong ngôn ngữ Lucene), và sau đó nhanh chóng kiểm tra trong các chỉ mục ngược mà tài liệu có các phần trong mẫu của bạn.

Bạn có thể lưu trữ siêu dữ liệu với các chỉ mục tài liệu để bạn có thể không phải tham khảo tệp lớn trong phần lớn các trường hợp sử dụng.

+0

Tệp tôi đang phân tích đang tăng theo thời gian. Có thể lập chỉ mục. Tôi chỉ thấy rằng biểu thức chính quy chậm hơn. Tôi phải sử dụng một cái gì đó giống như Thomson NFA. – Kamahire

+0

Cảm ơn Peter đã trả lời nhanh chóng. Làm thế nào có thể sử dụng Lucern cho cùng? Bạn có thể cho tôi một số mẫu không. – Kamahire

+0

Lucene là tốt cho xử lý dữ liệu văn bản với ngôn ngữ tự nhiên bên trong. Tùy thuộc vào định dạng tệp và mẫu của bạn, đây có thể không phải là giải pháp tốt nhất. –

4

Bạn có thể thử sử dụng các lớp Pattern và Matcher để tìm kiếm với các biểu thức đã biên dịch.

Xem http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.htmlhttp://download.oracle.com/javase/tutorial/essential/regex/

hoặc sử dụng công cụ tìm kiếm mà bạn yêu thích để tìm kiếm trên các điều khoản:

tối ưu hóa java biểu thức chính quy hoặc

hiệu suất java biểu thức chính quy

+0

Tôi đã tối ưu hóa các biểu thức chính quy. Tôi đã gỡ bỏ backtracking. – Kamahire

+1

Điều đó có làm cho nó nhanh hơn không? –

4

Tôi nghĩ nó phụ thuộc vào:

  • cấu trúc của dữ liệu của bạn (dòng định hướng?)
  • sự phức tạp của trận đấu
  • tốc độ mà tại đó các tập tin dữ liệu đang tăng trưởng

Nếu dữ liệu của bạn được dòng định hướng (hoặc khối định hướng) và một trận đấu phải xảy ra trong một đơn vị như vậy bạn có thể phù hợp cho đến khi khối hoàn thành cuối cùng, và lưu trữ vị trí tệp của điểm cuối đó. Lần quét tiếp theo sẽ bắt đầu tại điểm cuối đó (có thể sử dụng RandomAccessFile.seek()).

Điều này đặc biệt hữu ích nếu dữ liệu không phát triển nhanh chóng.

Nếu đối sánh của bạn rất phức tạp nhưng có văn bản cố định riêng biệt và mẫu không xuất hiện thường xuyên, bạn có thể nhanh hơn bằng String.contains() và chỉ khi điều đó thực sự áp dụng mẫu. Vì các mẫu có xu hướng được tối ưu hóa cao nên chắc chắn không đảm bảo sẽ nhanh hơn.

Bạn thậm chí có thể nghĩ đến việc thay thế regex bằng cách viết tay một trình phân tích cú pháp, có thể dựa trên StringTokenizer hoặc một số thứ như vậy. Đó chắc chắn là rất nhiều công việc để làm cho nó đúng, nhưng nó sẽ cho phép bạn vượt qua một số thông minh thêm về dữ liệu vào phân tích cú pháp, cho phép nó thất bại nhanh chóng. Điều này sẽ chỉ là một lựa chọn tốt nếu bạn thực sự biết rất nhiều về dữ liệu mà bạn không thể mã hóa trong một mẫu.

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