2010-09-24 13 views
13

मैं डेव डीलॉन्ग के उत्कृष्ट CHCSVParser के साथ ऑब्जेक्टिव-सी के लिए बहुत ही लंबे समय से सीएसवी फ़ाइल के साथ खेल रहा हूं और इसका उपयोग कर कुछ परेशानी में भाग रहा हूं। मैं arrayWithContentsOfCSVFile विधि का उपयोग करूंगा, लेकिन मैं एक आईफोन पर कोड चला रहा हूं और पूरी फाइल को स्मृति में पार्स कर रहा हूं, यह उपलब्ध होने से अधिक मेमोरी लेगा।CHCSVParser क्लास का उपयोग कैसे करें

नीचे दिए गए मेरे कोड में, पार्सर दस्तावेज़ खोलता है और प्रतिनिधि विधियों को पूरी तरह से कॉल करता है, लेकिन जहां प्रतिनिधि में मैं प्रत्येक पंक्ति के बाद रुक जाता हूं और डेटा तक पहुंचता हूं (डेटा स्टोर पर कोर डेटा ऑब्जेक्ट बनाने और सहेजने के लिए) ? मुझे लगता है कि - (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber में होगा, लेकिन मुझे लाइन के साथ किए जाने पर पार्सर से डेटा के NSArray (या जो भी) प्राप्त हो सकता है?

// 
// The code from a method in my view controller: 
// 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSFileManager *manager = [NSFileManager defaultManager]; 
NSError *err = nil; 
NSArray *fileList = [manager contentsOfDirectoryAtPath:documentsDirectory error:&err]; 
NSString *fileName = [fileList objectAtIndex:1]; 
NSURL *inputFileURL = [NSURL fileURLWithPath: [documentsDirectory stringByAppendingPathComponent:fileName]]; 


NSStringEncoding encoding = 0; 
CHCSVParser *p = [[CHCSVParser alloc] initWithContentsOfCSVFile:[inputFileURL path] usedEncoding:&encoding error:nil]; 
[p setParserDelegate:self]; 
[p parse]; 
[p release]; 

... 

#pragma mark - 
#pragma mark CHCSVParserDelegate methods 

- (void) parser:(CHCSVParser *)parser didStartDocument:(NSString *)csvFile { 
    NSLog(@"Parser started!"); 
} 

- (void) parser:(CHCSVParser *)parser didStartLine:(NSUInteger)lineNumber { 
    //NSLog(@"Parser started line: %i", lineNumber); 
} 

- (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber { 
    NSLog(@"Parser ended line: %i", lineNumber); 
} 

- (void) parser:(CHCSVParser *)parser didReadField:(NSString *)field { 
    //NSLog(@"Parser didReadField: %@", field); 
} 

- (void) parser:(CHCSVParser *)parser didEndDocument:(NSString *)csvFile { 
    NSLog(@"Parser ended document: %@", csvFile); 
} 

- (void) parser:(CHCSVParser *)parser didFailWithError:(NSError *)error { 
    NSLog(@"Parser failed with error: %@ %@", [error localizedDescription], [error userInfo]); 
} 

धन्यवाद:

यहाँ मेरी कोड अब तक है!

उत्तर

17

मुझे यह देखकर खुशी हो रही है कि मेरा कोड उपयोगी साबित हो रहा है! :)

CHCSVParserNSXMLParser पर व्यवहार में समान है, हर बार जब यह कुछ दिलचस्प लगता है, तो यह आपको एक प्रतिनिधि कॉलबैक के माध्यम से आपको बताने जा रहा है। हालांकि, अगर आप उस डेटा को अनदेखा करना चुनते हैं जो आपको कॉलबैक में देता है, तो यह चला गया है। ये पार्सर्स (CHCSVParser और NSXMLParser) बहुत बेवकूफ हैं। वे सिर्फ उन चीज़ों के प्रारूप को जानते हैं जिन्हें वे पार्स करने की कोशिश कर रहे हैं, लेकिन वास्तव में उससे परे बहुत कुछ नहीं करते हैं।

तो जवाब संक्षेप में, "आपको इसे स्वयं सहेजना है"। यदि आप NSArray श्रेणी के लिए कोड देखते हैं, तो आप .m फ़ाइल में देखेंगे कि यह a simple NSObject subclass as the parser delegate का उपयोग कर रहा है, और यह सबक्लस फ़ील्ड को सरणी में जोड़ रहा है, और उसके बाद उस सरणी को समग्र सरणी में जोड़ रहा है। आपको कुछ ऐसा करने की आवश्यकता होगी।

उदाहरण प्रतिनिधि:

@interface CSVParserDelegate : NSObject <CHCSVParserDelegate> { 
    NSMutableArray * currentRow; 
} 
@end 

@implementation CSVParserDelegate 

- (void) parser:(CHCSVParser *)parser didStartLine:(NSUInteger)lineNumber { 
    currentRow = [[NSMutableArray alloc] init]; 
} 
- (void) parser:(CHCSVParser *)parser didReadField:(NSString *)field { 
    [currentRow addObject:field]; 
} 
- (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber { 
    NSLog(@"finished line! %@", currentRow); 
    [self doSomethingWithLine:currentRow]; 
    [currentRow release], currentRow = nil; 
} 
@end 

हालांकि, मैं पार्सर पंक्ति में ही एकत्र करने के लिए के व्यवहार को संशोधित करने के लिए आश्वस्त हो सकता है, लेकिन अगर मैं उस मार्ग नीचे जाना, क्यों सिर्फ पार्सर कुल पूरे नहीं फाइल? (उत्तर: यह नहीं होना चाहिए)

+0

उत्तर के लिए धन्यवाद - मैं यह नहीं बता सका कि पार्सर ने आपके लिए यह काम किया है ('currentChunk' या किसी अन्य तरीके से)! यह अच्छा होगा कि मैन्युअल रूप से एकत्रीकरण नहीं करना पड़ेगा, लेकिन अधिकांश ऐप्स के लिए सीएसवी पार्सिंग केवल आई/ओ के लिए कुछ स्थानों में उपयोग की जाती है। अगर कोई उस कोड को थोड़ा सा लिखना चाहता था, तो क्या यह सबक्लास होना संभव होगा या CHCSVParserDelegate पर एक श्रेणी लिखें? –

+0

@Neal 'CHCSVParserDelegate' एक प्रोटोकॉल है, इसलिए आप इसे उपclass नहीं कर सकते हैं। इस व्यवहार को काम करने के लिए, आपको सीधे 'CHCSVParser' को बदलना होगा या इसे उपclass करना होगा। सबसे आसान जवाब लाइन को स्वयं जोड़ना है (जैसे मैं जवाब में करता हूं) –

+0

ऐसा नहीं सोचा था ... अच्छा काम यहाँ अद्भुत काम के लिए बहुत बहुत धन्यवाद! असल में आपके कोड में मामूली सुधार ... 'didEndLine' में हमें 'currentLine' को' currentRow 'में बदलने की आवश्यकता है। (मैं इसे बदल दूंगा लेकिन पर्याप्त एक्सपी नहीं है;)) –

1

मैंने आज @ डेवडेलोंग के उत्कृष्ट उत्तर और कोड के आधार पर इसका उपयोग करने का प्रयास किया, लेकिन मुझे लगता है कि सॉफ़्टवेयर को उनके (2010) के उत्तर के बाद संशोधित किया गया है। लेखन के समय, मैंने पाया कि मैं इस का उपयोग करने के लिए किया था:

@interface CSVParserDelegate : NSObject <CHCSVParserDelegate> { 
    NSMutableArray * currentRow; 
} 
@end 

@implementation CSVParserDelegate 

- (void) parser:(CHCSVParser *)parser didBeginLine:(NSUInteger)lineNumber { 
    currentRow = [[NSMutableArray alloc] init]; 
} 
- (void) parser:(CHCSVParser *)parser didReadField:(NSString *)field atIndex:(NSInteger)fieldIndex { 
    [currentRow addObject:field]; 
} 
- (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber { 
    NSLog(@"finished line! %@", currentRow); 
    [self doSomethingWithLine:currentRow]; 
    [currentRow release], currentRow = nil; 
} 
@end 

अर्थात, parser:didStartLine:lineNumber:parser:didBeginLine:lineNumber: बन गया है और parser:didReadField:parser:didReadField:atIndex: बन गया है।

संबंधित मुद्दे