2012-01-11 38 views
7

Tôi phải đọc một tệp văn bản lớn có dung lượng 25 GB và cần xử lý tệp này trong vòng 15-20 phút. Tệp này sẽ có nhiều phần đầu trang và chân trang.Đọc và xử lý tệp văn bản lớn 25GB

Tôi đã thử CSplit chia tệp này dựa trên tiêu đề, nhưng mất khoảng 24 đến 25 phút để chia nhỏ tệp thành một số tệp dựa trên tiêu đề, điều này hoàn toàn không chấp nhận được.

Tôi đã thử đọc và viết tuần tự bằng cách sử dụng BufferReaderBufferWiter cùng với FileReaderFileWriter. Mất hơn 27 phút. Một lần nữa, nó không được chấp nhận.

Tôi đã thử một cách tiếp cận khác như lấy chỉ mục bắt đầu của mỗi tiêu đề và sau đó chạy nhiều luồng để đọc tệp từ vị trí cụ thể bằng cách sử dụng RandomAccessFile. Nhưng không may mắn về điều này.

Làm cách nào để tôi có thể đạt được yêu cầu của mình?

có thể trùng lặp của:

Read large files in Java

Trả lời

7

Hãy thử sử dụng một bộ đệm lớn kích thước đọc (ví dụ, thay vì 20MB 2MB) để xử lý dữ liệu của bạn nhanh hơn. Cũng không sử dụng BufferedReader vì tốc độ chậm và chuyển đổi ký tự.

Câu hỏi này đã được hỏi trước: Read large files in Java

0

Hãy thử sử dụng java.nio để tận dụng tốt hơn các chức năng hệ điều hành. Tránh sao chép dữ liệu (ví dụ: thành một chuỗi), nhưng cố gắng làm việc với bù trừ. Tôi tin rằng các lớp java.nio thậm chí sẽ có các phương thức để chuyển dữ liệu từ bộ đệm này sang bộ đệm khác mà không cần kéo dữ liệu vào lớp java chút nào (ít nhất là trên Linux), nhưng về cơ bản sẽ chuyển thành các cuộc gọi hệ điều hành. Đối với nhiều máy chủ web hiện đại, kỹ thuật này là chìa khóa cho hiệu suất mà chúng có thể phục vụ dữ liệu tĩnh với: về cơ bản họ ủy quyền càng nhiều càng tốt cho hệ điều hành để tránh sao chép nó vào bộ nhớ chính.

Hãy để tôi nhấn mạnh điều này: chỉ tìm kiếm qua bộ đệm 25 GB byte nhanh hơn rất nhiều so với chuyển đổi thành Java Strings (có thể yêu cầu mã hóa/giải mã ký tự - và sao chép). Bất cứ thứ gì giúp bạn sao lưu và quản lý bộ nhớ sẽ giúp bạn.

+1

NIO có giới hạn xấu xí được thiết kế ngay trong đó: bạn có thể ánh xạ 2GB ở mức tốt nhất làm bộ đệm vì API bộ đệm sử dụng int cho tất cả bù trừ. Điều này làm cho nio cồng kềnh lúc tốt nhất cho các tập tin lớn. – Durandal

5

Bạn cần đảm bảo rằng IO đủ nhanh mà không cần xử lý vì tôi nghi ngờ việc xử lý, không phải IO đang làm chậm bạn xuống. Bạn sẽ có thể nhận được 80 MB/s từ một ổ đĩa cứng và lên đến 400 MB/s từ một ổ SSD. Điều này có nghĩa là bạn có thể đọc toàn bộ trong một giây.

Hãy thử cách sau, đây không phải là nhanh nhất, nhưng đơn giản nhất.

long start = System.nanoTime(); 
byte[] bytes = new byte[32*1024]; 
FileInputStream fis = new FileInputStream(fileName); 
int len; 
while((len = fis.read(bytes)) > 0); 
long time = System.nanoTime() - start; 
System.out.printf("Took %.3f seconds%n", time/1e9); 

Trừ khi bạn thấy mình đang gặp phải ít nhất 50 MB/s, bạn gặp sự cố phần cứng.

0

Nếu nền tảng phù hợp, bạn có thể muốn bóc vỏ và gọi kết hợp giữa mèo và sed. Nếu không, bạn vẫn có thể muốn thoát ra ngoài và sử dụng perl thông qua dòng lệnh. Đối với trường hợp đó là hoàn toàn phải được Java làm việc xử lý thực tế, những người khác đã cung cấp câu trả lời đầy đủ.

Hãy cảnh giác, bắn phá không phải là không có vấn đề gì. Nhưng perl hoặc sed có thể là công cụ có sẵn rộng rãi duy nhất để thu thập thông tin và thay đổi 25 GB văn bản trong khung thời gian của bạn.

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