2012-12-14 28 views
8

के लिए अच्छा और प्रभावी सीएसवी/टीएसवी रीडर मैं 1000000 पंक्तियों या उससे अधिक के साथ बड़े CSV और TSV (टैब सेपरेटेड) फ़ाइलों को पढ़ने की कोशिश कर रहा हूं। अब मैंने ~2500000 लाइनों को opencsv के साथ पढ़ने की कोशिश की, लेकिन यह मुझे java.lang.NullPointerException फेंकता है। यह ~250000 लाइनों वाली छोटी TSV फ़ाइलों के साथ काम करता है। तो मैं सोच रहा था कि क्या कोई अन्य Libraries है जो विशाल CSV और TSV फ़ाइलों के पढ़ने का समर्थन करता है। आपके पास कोई विचार है?जावा

हर कोई जो मेरी कोड में रुचि रखता है (मैं इसे छोटा है, तो जाहिर है Try-Catch अमान्य है):

InputStreamReader in = null; 
CSVReader reader = null; 
try { 
    in = this.replaceBackSlashes(); 
    reader = new CSVReader(in, this.seperator, '\"', this.offset); 
    ret = reader.readAll(); 
} finally { 
    try { 
     reader.close(); 
    } 
} 

संपादित करें:

private InputStreamReader replaceBackSlashes() throws Exception { 
     FileInputStream fis = null; 
     Scanner in = null; 
     try { 
      fis = new FileInputStream(this.csvFile); 
      in = new Scanner(fis, this.encoding); 
      ByteArrayOutputStream out = new ByteArrayOutputStream(); 

      while (in.hasNext()) { 
       String nextLine = in.nextLine().replace("\\", "/"); 
       // nextLine = nextLine.replaceAll(" ", ""); 
       nextLine = nextLine.replaceAll("'", ""); 
       out.write(nextLine.getBytes()); 
       out.write("\n".getBytes()); 
      } 

      return new InputStreamReader(new ByteArrayInputStream(out.toByteArray())); 
     } catch (Exception e) { 
      in.close(); 
      fis.close(); 
      this.logger.error("Problem at replaceBackSlashes", e); 
     } 
     throw new Exception(); 
    } 
+2

बुफर्ड रीडर के लिए धन्यवाद क्यों नहीं पढ़ते? –

+0

असल में मैं अच्छी तरह से तैयार किया गया था, सामान्य इस्तेमाल किया कोड और मैं पहिया को फिर से शुरू नहीं करना चाहता, असल में यही कारण है कि हर कोई libs का उपयोग कर रहा है। लेकिन अगर कुछ भी काम नहीं कर रहा है, तो मैं ऐसा करूँगा। – Robin

+2

उन कई पंक्तियों के साथ मैं बैच में फ़ाइल को संसाधित करने में देखता हूं: फ़ाइल से एन लाइनें पढ़ें, सीएसवी के साथ प्रक्रिया करें, अगले बैच आदि पढ़ें। – opi

उत्तर

5

मैं: इस विधि जहाँ मैं InputStreamReader का निर्माण है कोशिश नहीं की है, लेकिन मैंने पहले सुपरसीएसवी की जांच की थी।

http://sourceforge.net/projects/supercsv/

http://supercsv.sourceforge.net/

चेक है कि अगर आप के लिए काम करता है, 25 लाख लाइनों।

+0

धन्यवाद, मैं इस lib पर एक नज़र डालेगा। – Robin

+0

धन्यवाद। 'supercsv' '2 500 000' लाइनों को बहुत अच्छी तरह से संभालती है। – Robin

+2

@Robin एक सुपर सीएसवी डेवलपर मैं यह सुनने के लिए, हालांकि opencsv के लिए निष्पक्ष होना करने के लिए खुश हूँ के रूप में, आप अगर आप 'reader.readAll()' के बजाय प्रत्येक पंक्ति को पढ़ने का उपयोग (स्मृति) में समस्याएं आ रही करने के लिए बाध्य कर रहे हैं और इसके साथ कुछ कर रहा हूँ। आपकी 'replaceBackslashes()' विधि भी समस्याओं में चल सकती है क्योंकि आप पूरी फ़ाइल को स्मृति में लिख रहे हैं। क्या आपकी एनपीई आपकी धाराओं/पाठकों में से एक को बंद करते समय हो रही थी? –

1

Satish द्वारा सुझाए गए पुस्तकालयों को स्विच करने का प्रयास करें। अगर इससे मदद नहीं मिलती है, तो आपको पूरी फाइल को टोकन में विभाजित करना होगा और उन्हें संसाधित करना होगा।

में सोच रही थी कि अपने CSV अल्पविराम के

// r is the BufferedReader pointed at your file 
String line; 
StringBuilder file = new StringBuilder(); 
// load each line and append it to file. 
while ((line=r.readLine())!=null){ 
    file.append(line); 
} 
// Make them to an array 
String[] tokens = file.toString().split(","); 

तो फिर तुम इसे संसाधित कर सकते हैं के लिए किसी भी भागने पात्रों पड़ा। इसका उपयोग करने से पहले टोकन को ट्रिम करना न भूलें।

1

मुझे नहीं पता कि यह प्रश्न अभी भी सक्रिय है, लेकिन यहां मैं सफलतापूर्वक उपयोग करता हूं। फिर भी, इस तरह के स्ट्रीम या Iterable के रूप में अधिक इंटरफेस को लागू करने के लिए हो सकता है, लेकिन:

import java.io.Closeable; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.Scanner; 

/** Reader for the tab separated values format (a basic table format without escapings or anything where the rows are separated by tabulators).**/ 
public class TSVReader implements Closeable 
{ 
    final Scanner in; 
    String peekLine = null; 

    public TSVReader(InputStream stream) throws FileNotFoundException 
    { 
     in = new Scanner(stream); 
    } 

    /**Constructs a new TSVReader which produces values scanned from the specified input stream.*/ 
    public TSVReader(File f) throws FileNotFoundException {in = new Scanner(f);} 

    public boolean hasNextTokens() 
    { 
     if(peekLine!=null) return true; 
     if(!in.hasNextLine()) {return false;} 
     String line = in.nextLine().trim(); 
     if(line.isEmpty()) {return hasNextTokens();} 
     this.peekLine = line;  
     return true;   
    } 

    public String[] nextTokens() 
    { 
     if(!hasNextTokens()) return null;  
     String[] tokens = peekLine.split("[\\s\t]+"); 
//  System.out.println(Arrays.toString(tokens)); 
     peekLine=null;  
     return tokens; 
    } 

    @Override public void close() throws IOException {in.close();} 
} 
+0

असल में मैं सुपरसीएसवी से बहुत संतुष्ट हूं। हालांकि प्राकृतिक कार्यान्वयन के लिए धन्यवाद। – Robin

9

TSV आदानों पार्स करने के लिए एक सीएसवी पार्सर का उपयोग न करें। यदि टीएसवी में उद्धरण चरित्र के साथ फ़ील्ड हैं, तो यह तोड़ देगा।

uniVocity-parsers एक टीएसवी पार्सर के साथ आता है। आप समस्याओं के बिना एक अरब पंक्तियों का विश्लेषण कर सकते हैं।

उदाहरण एक TSV इनपुट पार्स करने के लिए:

TsvParserSettings settings = new TsvParserSettings(); 
TsvParser parser = new TsvParser(settings); 

// parses all rows in one go. 
List<String[]> allRows = parser.parseAll(new FileReader(yourFile)); 

यदि आपका इनपुट इतना बड़ा यह स्मृति में नहीं रखा जा सकता है, ऐसा करते हैं:

TsvParserSettings settings = new TsvParserSettings(); 

// all rows parsed from your input will be sent to this processor 
ObjectRowProcessor rowProcessor = new ObjectRowProcessor() { 
    @Override 
    public void rowProcessed(Object[] row, ParsingContext context) { 
     //here is the row. Let's just print it. 
     System.out.println(Arrays.toString(row)); 
    } 
}; 
// the ObjectRowProcessor supports conversions from String to whatever you need: 
// converts values in columns 2 and 5 to BigDecimal 
rowProcessor.convertIndexes(Conversions.toBigDecimal()).set(2, 5); 

// converts the values in columns "Description" and "Model". Applies trim and to lowercase to the values in these columns. 
rowProcessor.convertFields(Conversions.trim(), Conversions.toLowerCase()).set("Description", "Model"); 

//configures to use the RowProcessor 
settings.setRowProcessor(rowProcessor); 

TsvParser parser = new TsvParser(settings); 
//parses everything. All rows will be pumped into your RowProcessor. 
parser.parse(new FileReader(yourFile)); 

प्रकटीकरण: मैं कर रहा हूँ के लेखक यह पुस्तकालय यह ओपन-सोर्स और फ्री (अपाचे वी 2.0 लाइसेंस) है।

+1

आपने सेटिंग्स नहीं की हैं .setRowProcessor (rowProcessor); – userRaj

+1

धन्यवाद! मेरे पास है मेरा जवाब अपडेट किया गया। –