2012-01-12 3 views
7

में एक विशाल फ़ाइल.txt की सॉर्टिंग लाइनें मैं एक बहुत बड़ी टेक्स्ट फ़ाइल (755 एमबी) के साथ काम कर रहा हूं। मुझे लाइनों को क्रमबद्ध करने की आवश्यकता है (लगभग 18 9 0000) और फिर उन्हें दूसरी फ़ाइल में वापस लिखें।जावा

मैं पहले से ही है कि चर्चा एक प्रारंभिक फ़ाइल वास्तव में मेरा जैसी ही है कि देखा: Sorting Lines Based on words in them as keys

समस्या यह है कि मैं क्योंकि मैं एक जावा ढेर अंतरिक्ष अपवाद (भले ही मिल स्मृति में एक संग्रह में लाइनों संग्रहीत नहीं कर सकता है मैं अधिकतम पर इसका विस्तार) .. (पहले से ही करने की कोशिश की!)

मैं या तो एक्सेल के साथ यह नहीं खोल सकता और क्योंकि फ़ाइल बहुत बड़ी है छँटाई सुविधा का उपयोग और यह पूरी तरह से लोड नहीं किया जा सकता ..

मैं एक डीबी का उपयोग करने के बारे में सोचा .. लेकिन मुझे लगता है कि आप सभी लाइनों को लिखते हैं तो आप SELECT क्वेरी से निष्पादित समय के मामले में यह बहुत लंबा है..मैं गलत हूँ?

कोई संकेत सराहना अग्रिम

+0

अच्छा, "बहुत लंबा" आपकी अपेक्षाओं पर निर्भर करता है। यदि आप इसे आधे सेकेंड में करने की उम्मीद करते हैं, तो यह वास्तव में बहुत लंबा होगा। यदि आपको कुछ सेकंड या मिनट की प्रतीक्षा करने में कोई फर्क नहीं पड़ता है, तो यह कोई समस्या नहीं होनी चाहिए। इसे आज़माएं, और देखें कि समय उचित है या नहीं। –

+0

आप जावा के नवीनतम संस्करणों का उपयोग कर फ़ाइल को लगभग 1 जीबी ढेर के साथ मेमोरी में स्टोर करने में सक्षम होना चाहिए। यानी '-XX: + UseCompressedStrings' –

उत्तर

15

मुझे लगता है कि यहाँ समाधान तरह अस्थायी फ़ाइलों का उपयोग कर किसी मर्ज करने के लिए है:

  1. पहली फ़ाइल की पहली n पंक्तियां पढ़ें, (n उन पंक्तियों की संख्या होने के कारण जिन्हें आप स्टोर करने और स्मृति में सॉर्ट करने के लिए खर्च कर सकते हैं), उन्हें सॉर्ट करें और उन्हें 1.tmp फ़ाइल (या फिर आप इसे कॉल करें) पर लिखें। अगले n लाइनों के साथ ऐसा करें और इसे 2.tmp में संग्रहीत करें। तब तक दोहराएं जब तक कि मूल फ़ाइल की सभी पंक्तियों को संसाधित नहीं किया जाता है।

  2. प्रत्येक अस्थायी फ़ाइल की पहली पंक्ति पढ़ें। सबसे छोटा (अपने सॉर्ट ऑर्डर के अनुसार) निर्धारित करें, इसे गंतव्य फ़ाइल में लिखें, और संबंधित अस्थायी फ़ाइल से अगली पंक्ति पढ़ें। तब तक दोहराएं जब तक सभी लाइनों को संसाधित नहीं किया जाता है।

  3. सभी अस्थायी फ़ाइलों को हटाएं।

यह मनमाने ढंग से बड़ी फ़ाइलों के साथ काम करता है, जब तक आपके पास पर्याप्त डिस्क स्थान हो।

+0

मैं पूरी तरह से सहमत हूं। यह 'mergesort' एल्गोरिदम –

+4

+1 का उपयोग करके किया जा सकता है इसे "बहु-मार्ग विलय" कहा जाता है। – Tudor

0

क्यों आप multithreading और कार्यक्रम के बढ़ते ढेर आकार की कोशिश आप चल रहे हैं नहीं है धन्यवाद? (यह भी विलय तरह तरह की बात प्रदान की आप अपने सिस्टम में 755mb की तुलना में अधिक स्मृति का उपयोग करने की आवश्यकता है।)

+0

ऊपर Eric.Sun के लिए टिप्पणी छोड़ दी गई टिप्पणी देखें। –

+0

हां, आपका कारण बहुत ही बड़ी फाइलसाइज में स्पष्ट रूप से उपयोगी है। लेकिन ओपी निर्दिष्ट फ़ाइल आकार 755 एमबी होना है और अधिकांश कंप्यूटरों में आज 755 एमबी से अधिक है। एक जटिल एल्गोरिदम का उपयोग क्यों करें यदि हम उसकी समस्या को केवल -Xmx1024m के साथ हल कर सकते हैं? – javaCity

+1

मर्ज सॉर्ट एक अत्यधिक जटिल एल्गोरिदम नहीं है। मैं एल्गोरिदम द्वारा उपयोग किए गए हार्डवेयर पर धारणा नहीं बनाना चाहता था। साथ ही, यह प्रक्रिया डिवाइस पर चलने वाला एकमात्र सॉफ़्टवेयर नहीं हो सकता है। मेरी विनम्र राय में एक जीबी मेमोरी से अधिक बचाने के लिए कोड की 50 लाइनें लिख रही हैं (प्रत्येक पंक्ति स्ट्रिंग होने पर कई बाइट्स ले सकती है) प्रयास के लायक है। (कोई अपराध इरादा नहीं है।) –

1

एल्गोरिथ्म:

कितना स्मृति हम उपलब्ध है? आइए मान लें कि हमारे पास उपलब्ध स्मृति के X MB हैं।

  1. फूट डालो K हिस्सा है, जहां X * K = 2 GB में फ़ाइल। प्रत्येक खंड को स्मृति में लाएं और किसी भी O(n log n) एल्गोरिदम का उपयोग करके सामान्य रूप से लाइनों को क्रमबद्ध करें। लाइनों को वापस फाइल में सहेजें।

  2. अब अगले खंड को स्मृति और क्रम में लाएं।

  3. एक बार जब हम कर लेंगे, तो उन्हें एक-एक करके विलय करें।

उपरोक्त एल्गोरिदम को बाहरी प्रकार के रूप में भी जाना जाता है। चरण 3 को एन-वे मर्ज

-2

हो सकता है कि आप फ़ाइल को प्रारूपित करने के लिए perl का उपयोग कर सकें। और mysql जैसे डेटाबेस में लोड करें। यह बहुत तेज़ है। और डेटा पूछने के लिए सूचकांक का उपयोग करें। और दूसरी फाइल को लिखें।

यू '-Xms256m -Xmx1024m' मैं जैसे JVM ढेर आकार सेट कर सकते हैं मदद करने के लिए यू धन्यवाद

+0

फ़ाइल-आधारित विलय सॉर्ट का उपयोग करना अधिक मेमोरी आवंटित करने से कहीं बेहतर है। क्या होता है अगर फ़ाइल भी बड़ा हो, यानी 10gigs? –

1

आप

-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; 
    } 
} 

प्रिंट

के साथ निम्न चला सकते हैं आशा
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

क्या आप यह देखने के लिए jdk7u2 का उपयोग कर परीक्षण दोहरा सकते हैं कि कितनी मेमोरी और समय लगता है? – dogbane

+0

दुर्भाग्यवश जावा 7 इस विकल्प का समर्थन नहीं करता है http://stackoverflow.com/questions/8833385/is-support-for-compressed-strings-being- dropped –

+0

हाँ, लेकिन फिर भी यह देखना चाहेगा कि यह कितनी मेमोरी के बिना उपयोग करता है विकल्प। हो सकता है कि उन्होंने इस तरह के सुधार किए हैं कि इस विकल्प की अब आवश्यकता नहीं है। – dogbane