2012-01-12 11 views
7

Tôi đang làm việc với một tệp văn bản rất lớn (755Mb). Tôi cần sắp xếp các dòng (khoảng 1890000) và sau đó viết chúng lại trong một tệp khác.các dòng phân loại của một tệp tin rất lớn trong java

tôi đã nhận thấy rằng cuộc thảo luận mà có một tập tin khởi đầu thực sự tương tự như tôi: Sorting Lines Based on words in them as keys

Vấn đề là tôi không thể lưu trữ các dòng trong một bộ sưu tập trong bộ nhớ vì tôi nhận được một ngoại lệ Java Heap Space (ngay cả khi tôi mở rộng nó tối đa) .. (đã cố gắng!)

tôi không thể hoặc mở nó bằng excel và sử dụng các tính năng sắp xếp vì các tập tin quá lớn và nó không thể được hoàn toàn được tải ..

tôi suy nghĩ về việc sử dụng một DB .. nhưng tôi nghĩ rằng viết tất cả các dòng sau đó u se truy vấn SELECT nó quá dài về thời gian thực hiện .. tôi có sai không?

Bất kỳ gợi ý đánh giá cao Cảm ơn trước

+0

Vâng, "quá dài" tùy thuộc vào kỳ vọng của bạn. Nếu bạn hy vọng làm điều đó trong nửa giây, nó sẽ thực sự là quá dài. Nếu bạn không ngại chờ đợi một vài giây hoặc vài phút, nó không phải là một vấn đề. Hãy thử nó, và xem nếu thời gian là hợp lý. –

+0

Bạn sẽ có thể lưu trữ tệp trong bộ nhớ với khoảng 1 GB đống bằng cách sử dụng các phiên bản Java mới nhất. tức là với '-XX: + UseCompressedStrings' –

Trả lời

15

Tôi nghĩ rằng giải pháp ở đây là để làm việc kết hợp với loại sử dụng tập tin tạm thời:

  1. Hãy đọc n dòng đầu tiên của tệp đầu tiên, (n là số dòng bạn có thể lưu trữ và sắp xếp trong bộ nhớ), sắp xếp chúng và ghi chúng vào tệp 1.tmp (hoặc tuy nhiên bạn gọi nó). Làm tương tự với n dòng tiếp theo và lưu trữ nó trong 2.tmp. Lặp lại cho đến khi tất cả các dòng của tập tin gốc đã được xử lý.

  2. Đọc dòng đầu tiên của mỗi tệp tạm thời. Xác định phần nhỏ nhất (theo thứ tự sắp xếp của bạn), ghi nó vào tệp đích và đọc dòng tiếp theo từ tệp tạm thời tương ứng. Lặp lại cho đến khi tất cả các dòng đã được xử lý.

  3. Xóa tất cả các tệp tạm thời.

Điều này làm việc với các tệp lớn tùy ý, miễn là bạn có đủ dung lượng đĩa.

+0

Tôi hoàn toàn đồng ý. Nó có thể được thực hiện bằng cách sử dụng thuật toán 'mergesort' –

+4

+1 Điều này được gọi là "Kết hợp đa chiều". – Tudor

0

Tại sao bạn không thử đa luồng và tăng kích thước heap của chương trình bạn đang chạy? (Điều này cũng đòi hỏi bạn phải sử dụng merge sort loại điều miễn là bạn có nhiều bộ nhớ hơn 755mb trong hệ thống của bạn.)

+0

Xem nhận xét còn lại cho Eric.Sun ở trên. –

+0

Vâng, lý do của bạn rõ ràng là hữu ích trong việc kích thước rất lớn. Nhưng kích thước tệp được chỉ định OP là 755mb và hầu hết các máy tính hiện có hơn 755mb. Tại sao lại sử dụng một thuật toán phức tạp nếu chúng ta có thể giải quyết vấn đề của mình chỉ với -Xmx1024m? – javaCity

+1

Sắp xếp hợp nhất không phải là một thuật toán quá phức tạp. Tôi không muốn đưa ra các giả định về phần cứng được sử dụng bởi thuật toán. Ngoài ra, quá trình này có thể không phải là phần mềm duy nhất chạy trên thiết bị. Theo quan điểm khiêm tốn của tôi, viết 50 dòng mã để tiết kiệm hơn một GB bộ nhớ (mỗi dòng có thể mất vài byte, nếu là chuỗi) cũng đáng để thử. (Không có ý định vi phạm.) –

1

Thuật toán:

Bao nhiêu bộ nhớ chúng ta có sẵn? Giả sử chúng tôi có X MB bộ nhớ khả dụng.

  1. Chia tệp thành K khối, trong đó X * K = 2 GB. Đưa mỗi đoạn vào bộ nhớ và sắp xếp các dòng như bình thường bằng cách sử dụng bất kỳ thuật toán O(n log n) nào. Lưu các dòng trở lại tập tin.

  2. Bây giờ, hãy đưa đoạn tiếp theo vào bộ nhớ và sắp xếp.

  3. Sau khi hoàn tất, hãy hợp nhất từng cái một.

Thuật toán trên còn được gọi là sắp xếp bên ngoài. Bước 3 được gọi là Hợp nhất N-cách

-2

Có thể bạn có thể sử dụng perl để định dạng tệp .và tải vào cơ sở dữ liệu như mysql. nó quá nhanh. và sử dụng chỉ mục để truy vấn dữ liệu. và ghi vào một tập tin khác.

u có thể thiết lập kích thước JVM đống như .i '-Xms256m -Xmx1024m' hy vọng sẽ giúp u .thanks

+0

Sử dụng loại hợp nhất dựa trên tệp tốt hơn nhiều so với việc phân bổ nhiều bộ nhớ hơn. Điều gì sẽ xảy ra nếu tệp thậm chí còn lớn hơn, tức là 10gigs? –

1

Bạn có thể chạy sau với

-mx1g -XX:+UseCompressedStrings # on Java 6 update 29 
-mx1800m -XX:-UseCompressedStrings # on Java 6 update 29 
-mx2g # on Java 7 update 2. 

import java.io.*; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 

public class Main { 
    public static void main(String... args) throws IOException { 
     long start = System.nanoTime(); 
     generateFile("lines.txt", 755 * 1024 * 1024, 189000); 

     List<String> lines = loadLines("lines.txt"); 

     System.out.println("Sorting file"); 
     Collections.sort(lines); 
     System.out.println("... Sorted file"); 
     // save lines. 
     long time = System.nanoTime() - start; 
     System.out.printf("Took %.3f second to read, sort and write to a file%n", time/1e9); 
    } 

    private static void generateFile(String fileName, int size, int lines) throws FileNotFoundException { 
     System.out.println("Creating file to load"); 
     int lineSize = size/lines; 
     StringBuilder sb = new StringBuilder(); 
     while (sb.length() < lineSize) sb.append('-'); 
     String padding = sb.toString(); 

     PrintWriter pw = new PrintWriter(fileName); 
     for (int i = 0; i < lines; i++) { 
      String text = (i + padding).substring(0, lineSize); 
      pw.println(text); 
     } 
     pw.close(); 
     System.out.println("... Created file to load"); 
    } 

    private static List<String> loadLines(String fileName) throws IOException { 
     System.out.println("Reading file"); 
     BufferedReader br = new BufferedReader(new FileReader(fileName)); 
     List<String> ret = new ArrayList<String>(); 
     String line; 
     while ((line = br.readLine()) != null) 
      ret.add(line); 
     System.out.println("... Read file."); 
     return ret; 
    } 
} 

in

Creating file to load 
... Created file to load 
Reading file 
... Read file. 
Sorting file 
... Sorted file 
Took 4.886 second to read, sort and write to a file 
+0

Bạn có thể lặp lại thử nghiệm bằng cách sử dụng jdk7u2 để xem có bao nhiêu bộ nhớ và thời gian cần không? – dogbane

+0

Thật không may Java 7 không hỗ trợ tùy chọn này http://stackoverflow.com/questions/8833385/is-support-for-compressed-strings-being-dropped –

+0

Đúng, nhưng vẫn muốn xem dung lượng bộ nhớ mà nó không sử dụng tùy chọn. Có thể họ đã thực hiện các cải tiến sao cho tùy chọn này không còn cần thiết nữa. – dogbane