Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added support for parsing data from NSInputStreams. Updated README

  • Loading branch information...
commit 59858216b2b7f3c0daa01d5389be1165f4c0aa48 1 parent 2f93d86
@davedelong authored
View
20 CHCSVParser.h
@@ -31,27 +31,28 @@
@private
__weak id<CHCSVParserDelegate> parserDelegate;
- NSFileHandle * csvFileHandle;
- NSString * csvFile;
+ NSInputStream *csvReadStream;
+ BOOL endOfStreamReached;
NSStringEncoding fileEncoding;
+
+ NSString *csvFile;
BOOL hasStarted;
- NSString * delimiter;
+ NSString *delimiter;
unichar delimiterCharacter;
- NSMutableData * currentChunk;
- NSMutableString * currentChunkString;
+ NSMutableData *currentChunk;
+ NSMutableString *currentChunkString;
NSUInteger stringIndex;
- BOOL doneReadingFile;
BOOL balancedQuotes;
BOOL balancedEscapes;
- NSMutableString * currentField;
+ NSMutableString *currentField;
NSUInteger currentLine;
NSUInteger state;
- NSError * error;
+ NSError *error;
}
@property (assign) __weak id<CHCSVParserDelegate> parserDelegate;
@@ -59,6 +60,9 @@
@property (readonly) NSString * csvFile;
@property (nonatomic, copy) NSString *delimiter;
+- (id) initWithStream:(NSInputStream *)readStream usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)anError; //designated initializer
+- (id) initWithStream:(NSInputStream *)readStream encoding:(NSStringEncoding)encoding error:(NSError **)anError;
+
- (id) initWithContentsOfCSVFile:(NSString *)aCSVFile encoding:(NSStringEncoding)encoding error:(NSError **)anError;
- (id) initWithContentsOfCSVFile:(NSString *)aCSVFile usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)anError;
View
145 CHCSVParser.m
@@ -55,7 +55,7 @@ - (void) trimString_csv:(NSString *)character {
}
- (void) trimCharactersInSet_csv:(NSCharacterSet *)set {
- NSString * trimmed = [self stringByTrimmingCharactersInSet:set];
+ NSString *trimmed = [self stringByTrimmingCharactersInSet:set];
[self setString:trimmed];
}
@@ -67,10 +67,12 @@ - (void) replaceOccurrencesOfString:(NSString *)find withString_csv:(NSString *)
@interface CHCSVParser ()
-@property (retain) NSMutableData * currentChunk;
+@property (retain) NSMutableData *currentChunk;
- (NSStringEncoding) textEncodingForData:(NSData *)chunkToSniff offset:(NSUInteger *)offset;
+- (void) determineTextEncoding;
+- (void) readNextChunk;
- (NSString *) nextCharacter;
- (void) runParseLoop;
- (void) processComposedCharacter:(NSString *)currentCharacter previousCharacter:(NSString *)previousCharacter previousPreviousCharacter:(NSString *)previousPreviousCharacter;
@@ -87,19 +89,22 @@ - (void) finishCurrentLine;
@implementation CHCSVParser
@synthesize parserDelegate, currentChunk, error, csvFile, delimiter;
-- (id) initWithContentsOfCSVFile:(NSString *)aCSVFile encoding:(NSStringEncoding)encoding error:(NSError **)anError {
+- (id) initWithStream:(NSInputStream *)readStream usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)anError {
self = [super init];
- if (self) {
- csvFile = [aCSVFile copy];
- csvFileHandle = [[NSFileHandle fileHandleForReadingAtPath:csvFile] retain];
- if (csvFileHandle == nil) {
- if (anError) {
- *anError = [NSError errorWithDomain:@"com.davedelong.csv" code:0 userInfo:[NSDictionary dictionaryWithObject:@"Unable to open file for reading" forKey:NSLocalizedDescriptionKey]];
- }
- [self release];
- return nil;
- }
- fileEncoding = encoding;
+ if (self) {
+ csvReadStream = [readStream retain];
+ [csvReadStream open];
+
+ if (usedEncoding && *usedEncoding > 0) {
+ //if we're supplied an encoding, just use that
+ fileEncoding = *usedEncoding;
+ } else {
+ //otherwise try to guess
+ [self determineTextEncoding];
+ }
+ if (usedEncoding) {
+ *usedEncoding = fileEncoding;
+ }
balancedQuotes = YES;
balancedEscapes = YES;
@@ -107,62 +112,55 @@ - (id) initWithContentsOfCSVFile:(NSString *)aCSVFile encoding:(NSStringEncoding
currentLine = 0;
currentField = [[NSMutableString alloc] init];
- currentChunk = [[NSMutableData alloc] init];
- doneReadingFile = NO;
+ if (currentChunk == nil) {
+ currentChunk = [[NSMutableData alloc] init];
+ }
+ endOfStreamReached = NO;
currentChunkString = [[NSMutableString alloc] init];
stringIndex = 0;
[self setDelimiter:@","];
SETSTATE(CHCSVParserStateInsideFile)
- }
- return self;
+
+ }
+ return self;
+}
+
+- (id)initWithStream:(NSInputStream *)readStream encoding:(NSStringEncoding)encoding error:(NSError **)anError {
+ return [self initWithStream:readStream usedEncoding:&encoding error:anError];
+}
+
+- (id) initWithContentsOfCSVFile:(NSString *)aCSVFile encoding:(NSStringEncoding)encoding error:(NSError **)anError {
+ return [self initWithContentsOfCSVFile:aCSVFile usedEncoding:&encoding error:anError];
}
- (id) initWithContentsOfCSVFile:(NSString *)aCSVFile usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)anError {
- self = [self initWithContentsOfCSVFile:aCSVFile encoding:NSUTF8StringEncoding error:anError];
+ NSInputStream *readStream = [NSInputStream inputStreamWithFileAtPath:aCSVFile];
+ if (readStream == nil) {
+ if (anError) {
+ *anError = [NSError errorWithDomain:@"com.davedelong.csv" code:0 userInfo:[NSDictionary dictionaryWithObject:@"Unable to open file for reading" forKey:NSLocalizedDescriptionKey]];
+ }
+ [self release];
+ return nil;
+ }
+
+ self = [self initWithStream:readStream usedEncoding:usedEncoding error:anError];
if (self) {
-
- NSData * chunk = [csvFileHandle readDataOfLength:CHUNK_SIZE];
- NSUInteger seekOffset = 0;
- fileEncoding = [self textEncodingForData:chunk offset:&seekOffset];
- [csvFileHandle seekToFileOffset:seekOffset];
-
- [self setDelimiter:@","];
-
- if (usedEncoding) {
- *usedEncoding = fileEncoding;
- }
+ csvFile = [aCSVFile copy];
}
return self;
}
- (id) initWithCSVString:(NSString *)csvString encoding:(NSStringEncoding)encoding error:(NSError **)anError {
- self = [super init];
- if (self) {
- csvFile = nil;
- csvFileHandle = nil;
- fileEncoding = encoding;
-
- balancedQuotes = YES;
- balancedEscapes = YES;
-
- currentLine = 0;
- currentField = [[NSMutableString alloc] init];
-
- currentChunkString = [csvString mutableCopy];
- doneReadingFile = YES;
- stringIndex = 0;
-
- [self setDelimiter:@","];
-
- SETSTATE(CHCSVParserStateInsideFile)
- }
- return self;
+ return [self initWithStream:[NSInputStream inputStreamWithData:[csvString dataUsingEncoding:encoding]]
+ encoding:encoding
+ error:anError];
}
- (void) dealloc {
- [csvFileHandle release];
+ [csvReadStream close];
+ [csvReadStream release];
[csvFile release];
[currentField release];
[currentChunk release];
@@ -173,6 +171,21 @@ - (void) dealloc {
[super dealloc];
}
+- (void) determineTextEncoding {
+ uint8_t bytes[CHUNK_SIZE];
+ NSUInteger bytesRead = [csvReadStream read:bytes maxLength:CHUNK_SIZE];
+ currentChunk = [[NSMutableData alloc] initWithBytes:bytes length:bytesRead];
+
+ if ([currentChunk length] > 0) {
+ NSUInteger offset = 0;
+ fileEncoding = [self textEncodingForData:currentChunk offset:&offset];
+ if (offset > 0) {
+ // strip off the text encoding bytes
+ [currentChunk replaceBytesInRange:NSMakeRange(0, offset) withBytes:NULL];
+ }
+ }
+}
+
- (NSStringEncoding) textEncodingForData:(NSData *)chunkToSniff offset:(NSUInteger *)offset {
NSUInteger length = [chunkToSniff length];
*offset = 0;
@@ -256,11 +269,13 @@ - (void) setDelimiter:(NSString *)newDelimiter {
#pragma mark Parsing methods
- (void) readNextChunk {
- NSData * nextChunk = nil;
+ NSData *nextChunk = nil;
@try {
- nextChunk = [csvFileHandle readDataOfLength:CHUNK_SIZE];
+ uint8_t bytes[CHUNK_SIZE];
+ NSUInteger bytesRead = [csvReadStream read:bytes maxLength:CHUNK_SIZE];
+ nextChunk = [NSData dataWithBytes:bytes length:bytesRead];
}
- @catch (NSException * e) {
+ @catch (NSException *e) {
error = [[NSError alloc] initWithDomain:@"com.davedelong.csv" code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
e, NSUnderlyingErrorKey,
[e reason], NSLocalizedDescriptionKey,
@@ -293,13 +308,13 @@ - (void) readNextChunk {
[currentChunk replaceBytesInRange:NSMakeRange(0, readLength) withBytes:NULL length:0];
}
- if ([nextChunk length] < CHUNK_SIZE) {
- doneReadingFile = YES;
+ if ([csvReadStream streamStatus] == NSStreamStatusAtEnd) {
+ endOfStreamReached = YES;
}
}
- (NSString *) nextCharacter {
- if (doneReadingFile == NO && stringIndex >= [currentChunkString length]/2) {
+ if (endOfStreamReached == NO && stringIndex >= [currentChunkString length]/2) {
[self readNextChunk];
}
@@ -307,7 +322,7 @@ - (NSString *) nextCharacter {
if ([currentChunkString length] == 0) { return nil; }
NSRange charRange = [currentChunkString rangeOfComposedCharacterSequenceAtIndex:stringIndex];
- NSString * nextChar = [currentChunkString substringWithRange:charRange];
+ NSString *nextChar = [currentChunkString substringWithRange:charRange];
stringIndex = charRange.location + charRange.length;
return nextChar;
}
@@ -327,11 +342,11 @@ - (void) parse {
}
- (void) runParseLoop {
- NSString * currentCharacter = nil;
- NSString * previousCharacter = nil;
- NSString * previousPreviousCharacter = nil;
+ NSString *currentCharacter = nil;
+ NSString *previousCharacter = nil;
+ NSString *previousPreviousCharacter = nil;
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
unsigned char counter = 0;
while (error == nil &&
@@ -425,7 +440,7 @@ - (void) processComposedCharacter:(NSString *)currentCharacter previousCharacter
}
} else {
if (previousUnichar == UNICHAR_QUOTE && previousPreviousUnichar != UNICHAR_BACKSLASH && balancedQuotes == YES && balancedEscapes == YES) {
- NSString * reason = [NSString stringWithFormat:@"Invalid CSV format on line #%lu immediately after \"%@\"", currentLine, currentField];
+ NSString *reason = [NSString stringWithFormat:@"Invalid CSV format on line #%lu immediately after \"%@\"", currentLine, currentField];
error = [[NSError alloc] initWithDomain:@"com.davedelong.csv" code:0 userInfo:[NSDictionary dictionaryWithObject:reason forKey:NSLocalizedDescriptionKey]];
return;
}
@@ -482,7 +497,7 @@ - (void) finishCurrentField {
nextSlash = [currentField rangeOfString:STRING_BACKSLASH options:NSLiteralSearch range:nextSearchRange];
}
- NSString * field = [currentField copy];
+ NSString *field = [currentField copy];
[[self parserDelegate] parser:self didReadField:field];
[field release];
View
8 CHCSVParser.xcodeproj/project.pbxproj
@@ -8,9 +8,7 @@
/* Begin PBXBuildFile section */
5516BCB512578CFC0025F235 /* NSString+CHCSVAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5516BCB412578CFC0025F235 /* NSString+CHCSVAdditions.m */; };
- 5516BCB912578D750025F235 /* CHCSVSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 5516BCB812578D750025F235 /* CHCSVSupport.m */; };
5516BCBB12578EA90025F235 /* NSString+CHCSVAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5516BCB412578CFC0025F235 /* NSString+CHCSVAdditions.m */; };
- 5516BCBC12578EAD0025F235 /* CHCSVSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 5516BCB812578D750025F235 /* CHCSVSupport.m */; };
551981D61203715400FBE033 /* CHCSVParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 551981D51203715400FBE033 /* CHCSVParser.m */; };
5538B52D1344F0A1004930DD /* test.tsv in Resources */ = {isa = PBXBuildFile; fileRef = 5538B52C1344F0A1004930DD /* test.tsv */; };
557FCEB61203F938009FCDBA /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 557FCEB51203F938009FCDBA /* CoreServices.framework */; };
@@ -46,8 +44,6 @@
5516BCB312578CFC0025F235 /* NSString+CHCSVAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+CHCSVAdditions.h"; sourceTree = "<group>"; };
5516BCB412578CFC0025F235 /* NSString+CHCSVAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+CHCSVAdditions.m"; sourceTree = "<group>"; };
5516BCB612578D480025F235 /* CHCSV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHCSV.h; sourceTree = "<group>"; };
- 5516BCB712578D750025F235 /* CHCSVSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHCSVSupport.h; sourceTree = "<group>"; };
- 5516BCB812578D750025F235 /* CHCSVSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CHCSVSupport.m; sourceTree = "<group>"; };
551981D41203715400FBE033 /* CHCSVParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHCSVParser.h; sourceTree = "<group>"; };
551981D51203715400FBE033 /* CHCSVParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CHCSVParser.m; sourceTree = "<group>"; };
551981EE1203800300FBE033 /* Test.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Test.csv; sourceTree = "<group>"; };
@@ -137,8 +133,6 @@
551981D51203715400FBE033 /* CHCSVParser.m */,
55EFC7B71210608C0070B303 /* CHCSVWriter.h */,
55EFC7B81210608C0070B303 /* CHCSVWriter.m */,
- 5516BCB712578D750025F235 /* CHCSVSupport.h */,
- 5516BCB812578D750025F235 /* CHCSVSupport.m */,
557FD0411204A45D009FCDBA /* NSArray+CHCSVAdditions.h */,
557FD0421204A45D009FCDBA /* NSArray+CHCSVAdditions.m */,
5516BCB312578CFC0025F235 /* NSString+CHCSVAdditions.h */,
@@ -257,7 +251,6 @@
557FD05D1204A731009FCDBA /* UnitTests.m in Sources */,
55EFC7B91210608C0070B303 /* CHCSVWriter.m in Sources */,
5516BCB512578CFC0025F235 /* NSString+CHCSVAdditions.m in Sources */,
- 5516BCB912578D750025F235 /* CHCSVSupport.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -269,7 +262,6 @@
551981D61203715400FBE033 /* CHCSVParser.m in Sources */,
557FD0431204A45D009FCDBA /* NSArray+CHCSVAdditions.m in Sources */,
5516BCBB12578EA90025F235 /* NSString+CHCSVAdditions.m in Sources */,
- 5516BCBC12578EAD0025F235 /* CHCSVSupport.m in Sources */,
55BB40E612A367A500A1BB33 /* CHCSVWriter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
View
5,135 CHCSVParser.xcodeproj/project.xcworkspace/xcuserdata/dave.xcuserdatad/UserInterfaceState.xcuserstate
5,135 additions, 0 deletions not shown
View
10 CHCSVParser.xcodeproj/project.xcworkspace/xcuserdata/dave.xcuserdatad/WorkspaceSettings.xcsettings
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
+ <true/>
+ <key>IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges</key>
+ <false/>
+</dict>
+</plist>
View
5 CHCSVParser.xcodeproj/xcuserdata/dave.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Bucket
- type = "1"
- version = "1.0">
-</Bucket>
View
76 CHCSVParser.xcodeproj/xcuserdata/dave.xcuserdatad/xcschemes/CHCSVParser.xcscheme
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
- version = "1.3">
- <BuildAction
- parallelizeBuildables = "YES"
- buildImplicitDependencies = "YES">
- <BuildActionEntries>
- <BuildActionEntry
- buildForTesting = "YES"
- buildForRunning = "YES"
- buildForProfiling = "YES"
- buildForArchiving = "YES"
- buildForAnalyzing = "YES">
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "8DD76F960486AA7600D96B5E"
- BuildableName = "CHCSVParser"
- BlueprintName = "CHCSVParser"
- ReferencedContainer = "container:CHCSVParser.xcodeproj">
- </BuildableReference>
- </BuildActionEntry>
- </BuildActionEntries>
- </BuildAction>
- <TestAction
- selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
- shouldUseLaunchSchemeArgsEnv = "YES"
- buildConfiguration = "Debug">
- <Testables>
- </Testables>
- </TestAction>
- <LaunchAction
- selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
- displayScaleIsEnabled = "NO"
- displayScale = "1.00"
- launchStyle = "0"
- useCustomWorkingDirectory = "NO"
- buildConfiguration = "Debug">
- <BuildableProductRunnable>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "8DD76F960486AA7600D96B5E"
- BuildableName = "CHCSVParser"
- BlueprintName = "CHCSVParser"
- ReferencedContainer = "container:CHCSVParser.xcodeproj">
- </BuildableReference>
- </BuildableProductRunnable>
- <AdditionalOptions>
- </AdditionalOptions>
- </LaunchAction>
- <ProfileAction
- displayScaleIsEnabled = "NO"
- displayScale = "1.00"
- shouldUseLaunchSchemeArgsEnv = "YES"
- savedToolIdentifier = ""
- useCustomWorkingDirectory = "NO"
- buildConfiguration = "Release">
- <BuildableProductRunnable>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "8DD76F960486AA7600D96B5E"
- BuildableName = "CHCSVParser"
- BlueprintName = "CHCSVParser"
- ReferencedContainer = "container:CHCSVParser.xcodeproj">
- </BuildableReference>
- </BuildableProductRunnable>
- </ProfileAction>
- <AnalyzeAction
- buildConfiguration = "Debug">
- </AnalyzeAction>
- <ArchiveAction
- buildConfiguration = "Release"
- revealArchiveInOrganizer = "YES">
- </ArchiveAction>
-</Scheme>
View
52 CHCSVParser.xcodeproj/xcuserdata/dave.xcuserdatad/xcschemes/Unit Tests.xcscheme
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
- version = "1.3">
- <BuildAction
- parallelizeBuildables = "YES"
- buildImplicitDependencies = "YES">
- </BuildAction>
- <TestAction
- selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
- shouldUseLaunchSchemeArgsEnv = "YES"
- buildConfiguration = "Debug">
- <Testables>
- <TestableReference
- skipped = "NO">
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "557FD0521204A70D009FCDBA"
- BuildableName = "Unit Tests.octest"
- BlueprintName = "Unit Tests"
- ReferencedContainer = "container:CHCSVParser.xcodeproj">
- </BuildableReference>
- </TestableReference>
- </Testables>
- </TestAction>
- <LaunchAction
- selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
- displayScaleIsEnabled = "NO"
- displayScale = "1.00"
- launchStyle = "0"
- useCustomWorkingDirectory = "NO"
- buildConfiguration = "Debug">
- <AdditionalOptions>
- </AdditionalOptions>
- </LaunchAction>
- <ProfileAction
- displayScaleIsEnabled = "NO"
- displayScale = "1.00"
- shouldUseLaunchSchemeArgsEnv = "YES"
- savedToolIdentifier = ""
- useCustomWorkingDirectory = "NO"
- buildConfiguration = "Release">
- </ProfileAction>
- <AnalyzeAction
- buildConfiguration = "Debug">
- </AnalyzeAction>
- <ArchiveAction
- buildConfiguration = "Release"
- revealArchiveInOrganizer = "YES">
- </ArchiveAction>
-</Scheme>
View
32 CHCSVParser.xcodeproj/xcuserdata/dave.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>SchemeUserState</key>
- <dict>
- <key>CHCSVParser.xcscheme</key>
- <dict>
- <key>orderHint</key>
- <integer>0</integer>
- </dict>
- <key>Unit Tests.xcscheme</key>
- <dict>
- <key>orderHint</key>
- <integer>1</integer>
- </dict>
- </dict>
- <key>SuppressBuildableAutocreation</key>
- <dict>
- <key>557FD0521204A70D009FCDBA</key>
- <dict>
- <key>primary</key>
- <true/>
- </dict>
- <key>8DD76F960486AA7600D96B5E</key>
- <dict>
- <key>primary</key>
- <true/>
- </dict>
- </dict>
-</dict>
-</plist>
View
38 CHCSVSupport.h
@@ -1,38 +0,0 @@
-//
-// CHCSVSupport.h
-// CHCSVParser
-/**
- Copyright (c) 2010 Dave DeLong
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- **/
-
-#import <Foundation/Foundation.h>
-#import "CHCSVParser.h"
-
-@interface NSArrayCHCSVAggregator : NSObject <CHCSVParserDelegate> {
- NSMutableArray * lines;
- NSMutableArray * currentLine;
- NSError * error;
-}
-
-@property (readonly) NSArray * lines;
-@property (readonly) NSError * error;
-
-@end
View
66 CHCSVSupport.m
@@ -1,66 +0,0 @@
-//
-// CHCSVSupport.m
-// CHCSVParser
-/**
- Copyright (c) 2010 Dave DeLong
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- **/
-
-#import "CHCSVSupport.h"
-
-
-@implementation NSArrayCHCSVAggregator
-@synthesize lines, error;
-
-- (void) dealloc {
- [lines release];
- [currentLine release];
- [error release];
- [super dealloc];
-}
-
-- (void) parser:(CHCSVParser *)parser didStartDocument:(NSString *)csvFile {
- lines = [[NSMutableArray alloc] init];
-}
-
-- (void) parser:(CHCSVParser *)parser didStartLine:(NSUInteger)lineNumber {
- currentLine = [[NSMutableArray alloc] init];
-}
-
-- (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber {
- if ([currentLine count] > 0) {
- [lines addObject:currentLine];
- }
- [currentLine release], currentLine = nil;
-}
-
-- (void) parser:(CHCSVParser *)parser didReadField:(NSString *)field {
- [currentLine addObject:field];
-}
-
-- (void) parser:(CHCSVParser *)parser didEndDocument:(NSString *)csvFile {
-
-}
-
-- (void) parser:(CHCSVParser *)parser didFailWithError:(NSError *)anError {
- error = [anError retain];
-}
-
-@end
View
8 NSArray+CHCSVAdditions.h
@@ -28,6 +28,14 @@
@interface NSArray (CHCSVAdditions)
++ (id) arrayWithContentsOfCSVStream:(NSInputStream *)csvStream encoding:(NSStringEncoding)encoding error:(NSError **)error;
+- (id) initWithContentsOfCSVStream:(NSInputStream *)csvStream encoding:(NSStringEncoding)encoding error:(NSError **)error;
+- (id) initWithContentsOfCSVStream:(NSInputStream *)csvStream encoding:(NSStringEncoding)encoding delimiter:(NSString *)delimiter error:(NSError **)error;
+
++ (id) arrayWithContentsOfCSVStream:(NSInputStream *)csvStream usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)error;
+- (id) initWithContentsOfCSVStream:(NSInputStream *)csvStream usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)error;
+- (id) initWithContentsOfCSVStream:(NSInputStream *)csvStream usedEncoding:(NSStringEncoding *)usedEncoding delimiter:(NSString *)delimiter error:(NSError **)error;
+
+ (id) arrayWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding error:(NSError **)error;
- (id) initWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding error:(NSError **)error;
- (id) initWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding delimiter:(NSString *)delimiter error:(NSError **)error;
View
137 NSArray+CHCSVAdditions.m
@@ -26,64 +26,84 @@ of this software and associated documentation files (the "Software"), to deal
#import "NSArray+CHCSVAdditions.h"
#import "CHCSVParser.h"
#import "CHCSVWriter.h"
-#import "CHCSVSupport.h"
-@implementation NSArray (CHCSVAdditions)
+#pragma mark Support
-+ (id) arrayWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding error:(NSError **)error {
- return [[[self alloc] initWithContentsOfCSVFile:csvFile encoding:encoding error:error] autorelease];
+@interface NSArrayCHCSVAggregator : NSObject <CHCSVParserDelegate> {
+ NSMutableArray * lines;
+ NSMutableArray * currentLine;
+ NSError * error;
}
-- (id) initWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding error:(NSError **)error {
- return [self initWithContentsOfCSVFile:csvFile encoding:encoding delimiter:@"," error:error];
-}
+@property (readonly) NSArray * lines;
+@property (readonly) NSError * error;
-- (id) initWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding delimiter:(NSString *)delimiter error:(NSError **)error {
- if (error) { *error = nil; }
- NSString * rawCSV = [NSString stringWithContentsOfFile:csvFile encoding:encoding error:error];
- if ((error && *error) || rawCSV == nil) {
- [self release];
- return nil;
- }
- return [self initWithContentsOfCSVString:rawCSV encoding:encoding delimiter:delimiter error:error];
+@end
+
+@implementation NSArrayCHCSVAggregator
+@synthesize lines, error;
+
+- (void) dealloc {
+ [lines release];
+ [currentLine release];
+ [error release];
+ [super dealloc];
}
-+ (id) arrayWithContentsOfCSVFile:(NSString *)csvFile usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)error {
- return [[[self alloc] initWithContentsOfCSVFile:csvFile usedEncoding:usedEncoding error:error] autorelease];
+- (void) parser:(CHCSVParser *)parser didStartDocument:(NSString *)csvFile {
+ lines = [[NSMutableArray alloc] init];
}
-- (id) initWithContentsOfCSVFile:(NSString *)csvFile usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)error {
- return [self initWithContentsOfCSVFile:csvFile usedEncoding:usedEncoding delimiter:@"," error:error];
+- (void) parser:(CHCSVParser *)parser didStartLine:(NSUInteger)lineNumber {
+ currentLine = [[NSMutableArray alloc] init];
}
-- (id) initWithContentsOfCSVFile:(NSString *)csvFile usedEncoding:(NSStringEncoding *)usedEncoding delimiter:(NSString *)delimiter error:(NSError **)error {
- NSError *localError = nil;
- NSString * rawCSV = [NSString stringWithContentsOfFile:csvFile usedEncoding:usedEncoding error:&localError];
- if (rawCSV == nil) {
- if (error) { *error = [[localError retain] autorelease]; }
- if (usedEncoding) { *usedEncoding = NSMacOSRomanStringEncoding; }
-
- rawCSV = [NSString stringWithContentsOfFile:csvFile encoding:NSMacOSRomanStringEncoding error:&localError];
- }
- if (rawCSV == nil) {
- if (error) { *error = [[localError retain] autorelease]; }
- [self release];
- return nil;
+- (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber {
+ if ([currentLine count] > 0) {
+ [lines addObject:currentLine];
}
+ [currentLine release], currentLine = nil;
+}
+
+- (void) parser:(CHCSVParser *)parser didReadField:(NSString *)field {
+ [currentLine addObject:field];
+}
+
+- (void) parser:(CHCSVParser *)parser didEndDocument:(NSString *)csvFile {
- return [self initWithContentsOfCSVString:rawCSV encoding:(usedEncoding ? *usedEncoding : NSMacOSRomanStringEncoding) delimiter:delimiter error:error];
}
-+ (id) arrayWithContentsOfCSVString:(NSString *)csvString encoding:(NSStringEncoding)encoding error:(NSError **)error {
- return [[[self alloc] initWithContentsOfCSVString:csvString encoding:encoding error:error] autorelease];
+- (void) parser:(CHCSVParser *)parser didFailWithError:(NSError *)anError {
+ error = [anError retain];
}
-- (id) initWithContentsOfCSVString:(NSString *)csvString encoding:(NSStringEncoding)encoding error:(NSError **)error {
- return [self initWithContentsOfCSVString:csvString encoding:encoding delimiter:@"," error:error];
+@end
+
+#pragma mark NSArray Category
+
+@implementation NSArray (CHCSVAdditions)
+
++ (id) arrayWithContentsOfCSVStream:(NSInputStream *)csvStream encoding:(NSStringEncoding)encoding error:(NSError **)error {
+ return [[[self alloc] initWithContentsOfCSVStream:csvStream encoding:encoding error:error] autorelease];
+}
+- (id) initWithContentsOfCSVStream:(NSInputStream *)csvStream encoding:(NSStringEncoding)encoding error:(NSError **)error {
+ return [self initWithContentsOfCSVStream:csvStream encoding:encoding delimiter:@"," error:error];
+}
+- (id) initWithContentsOfCSVStream:(NSInputStream *)csvStream encoding:(NSStringEncoding)encoding delimiter:(NSString *)delimiter error:(NSError **)error {
+ return [self initWithContentsOfCSVStream:csvStream usedEncoding:&encoding delimiter:delimiter error:error];
}
-- (id) initWithContentsOfCSVString:(NSString *)csvString encoding:(NSStringEncoding)encoding delimiter:(NSString *)delimiter error:(NSError **)error {
- CHCSVParser * parser = [[CHCSVParser alloc] initWithCSVString:csvString encoding:encoding error:error];
++ (id) arrayWithContentsOfCSVStream:(NSInputStream *)csvStream usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)error {
+ return [[[self alloc] initWithContentsOfCSVStream:csvStream usedEncoding:usedEncoding error:error] autorelease];
+}
+- (id) initWithContentsOfCSVStream:(NSInputStream *)csvStream usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)error {
+ return [self initWithContentsOfCSVStream:csvStream usedEncoding:usedEncoding delimiter:@"," error:error];
+}
+- (id) initWithContentsOfCSVStream:(NSInputStream *)csvStream usedEncoding:(NSStringEncoding *)usedEncoding delimiter:(NSString *)delimiter error:(NSError **)error {
+ //THIS IS THE "DESIGNATED" INITIALIZER
+ //all other CSV initializers run through this one
+
+ CHCSVParser *parser = [[CHCSVParser alloc] initWithStream:csvStream usedEncoding:usedEncoding error:error];
[parser setDelimiter:delimiter];
NSArrayCHCSVAggregator * delegate = [[NSArrayCHCSVAggregator alloc] init];
[parser setParserDelegate:delegate];
@@ -106,6 +126,45 @@ - (id) initWithContentsOfCSVString:(NSString *)csvString encoding:(NSStringEncod
return [self initWithArray:lines];
}
++ (id) arrayWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding error:(NSError **)error {
+ return [[[self alloc] initWithContentsOfCSVFile:csvFile encoding:encoding error:error] autorelease];
+}
+
+- (id) initWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding error:(NSError **)error {
+ return [self initWithContentsOfCSVFile:csvFile encoding:encoding delimiter:@"," error:error];
+}
+
+- (id) initWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding delimiter:(NSString *)delimiter error:(NSError **)error {
+ NSInputStream *csvStream = [NSInputStream inputStreamWithFileAtPath:csvFile];
+ return [self initWithContentsOfCSVStream:csvStream encoding:encoding delimiter:delimiter error:error];
+}
+
++ (id) arrayWithContentsOfCSVFile:(NSString *)csvFile usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)error {
+ return [[[self alloc] initWithContentsOfCSVFile:csvFile usedEncoding:usedEncoding error:error] autorelease];
+}
+
+- (id) initWithContentsOfCSVFile:(NSString *)csvFile usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)error {
+ return [self initWithContentsOfCSVFile:csvFile usedEncoding:usedEncoding delimiter:@"," error:error];
+}
+
+- (id) initWithContentsOfCSVFile:(NSString *)csvFile usedEncoding:(NSStringEncoding *)usedEncoding delimiter:(NSString *)delimiter error:(NSError **)error {
+ NSInputStream *csvStream = [NSInputStream inputStreamWithFileAtPath:csvFile];
+ return [self initWithContentsOfCSVStream:csvStream usedEncoding:usedEncoding delimiter:delimiter error:error];
+}
+
++ (id) arrayWithContentsOfCSVString:(NSString *)csvString encoding:(NSStringEncoding)encoding error:(NSError **)error {
+ return [[[self alloc] initWithContentsOfCSVString:csvString encoding:encoding error:error] autorelease];
+}
+
+- (id) initWithContentsOfCSVString:(NSString *)csvString encoding:(NSStringEncoding)encoding error:(NSError **)error {
+ return [self initWithContentsOfCSVString:csvString encoding:encoding delimiter:@"," error:error];
+}
+
+- (id) initWithContentsOfCSVString:(NSString *)csvString encoding:(NSStringEncoding)encoding delimiter:(NSString *)delimiter error:(NSError **)error {
+ NSInputStream *csvStream = [NSInputStream inputStreamWithData:[csvString dataUsingEncoding:encoding]];
+ return [self initWithContentsOfCSVStream:csvStream encoding:encoding delimiter:delimiter error:error];
+}
+
- (BOOL) writeToCSVFile:(NSString *)csvFile atomically:(BOOL)atomically error:(NSError **)error {
return [self writeToCSVFile:csvFile withDelimiter:@"," atomically:atomically error:error];
}
View
48 README.markdown
@@ -13,38 +13,37 @@
###Parsing
In order to parse CSV files, you'll need `CHCSVParser.h` and `CHCSVParser.m`. A `CHCSVParser` works very similarly to an `NSXMLParser`, in that it synchronously parses the data and invokes delegate callback methods to let you know that it has found a field, or has finished reading a line, or has encountered a syntax error.
-A `CHCSVParser` can be created either with a path to a CSV file, or with an `NSString` of CSV data.
+A `CHCSVParser` can be created in one of three ways:
-###Writing
-In order to write data to a CSV file, you'll need `CHCSVWriter.h` and `CHCSVWriter.m`. A `CHCSVWriter` has 2 primary methods (beyond the designated initializer): `writeField:` and `writeLine`.
+1. With a path to a file
+2. With the contents of an `NSString`
+3. With an `NSInputStream`
-`writeField:` accepts an object and writes its `-description` (after being properly escaped) out to the CSV file. It will also write field seperator (`,`) if necessary. You may pass an empty string (`@""`) or `nil` to write an empty field.
+`CHCSVParser` can be configured to parse other "character-seperated" file formats, such as "TSV" (tab-seperated). You can change the delimiter of the parser prior to beginning parsing. The delimiter can only be one character in length, and cannot be any newline character, `#`, `"`, or `\`.
-`writeLine` is used to terminate the current CSV line. If you do not invoke `writeLine`, then all of your CSV fields will be on a single line.
+###Writing
+In order to write data to a CSV file, you'll need `CHCSVWriter.h` and `CHCSVWriter.m`. A `CHCSVWriter` has several methods for constructing CSV files:
-###Convenience Methods
-Included in the code is an `NSArray` category to simplify reading from and writing to CSV files. In order to use these methods, you must include `CHCSVParser.*`, `CHCSVWriter.*`, and `NSArray+CHCSVAdditions.*` in your project (all six files). This category adds 7 methods to `NSArray`: three class methods, three initializers, and one write method:
+`-writeField:` accepts an object and writes its `-description` (after being properly escaped) out to the CSV file. It will also write field seperator (`,`) if necessary. You may pass an empty string (`@""`) or `nil` to write an empty field.
-- `+ (id) arrayWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding error:(NSError **)error;`
-- `- (id) initWithContentsOfCSVFile:(NSString *)csvFile encoding:(NSStringEncoding)encoding error:(NSError **)error;`
+`-writeFields:` accepts a comma-delimited and nil-terminated list of objects and sends each one to `-writeField:`.
-- `+ (id) arrayWithContentsOfCSVFile:(NSString *)csvFile usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)error;`
-- `- (id) initWithContentsOfCSVFile:(NSString *)csvFile usedEncoding:(NSStringEncoding *)usedEncoding error:(NSError **)error;`
+`-writeLine` is used to terminate the current CSV line. If you do not invoke `-writeLine`, then all of your CSV fields will be on a single line.
-- `+ (id) arrayWithContentsOfCSVString:(NSString *)csvString encoding:(NSStringEncoding)encoding error:(NSError **)error;`
-- `- (id) initWithContentsOfCSVString:(NSString *)csvString encoding:(NSStringEncoding)encoding error:(NSError **)error;`
+`-writeLineOfFields:` accepts a comma-delimited and nil-terminated list of objects, sends each one to `-writeField:`, and then invokes `-writeLine`.
-- `- (BOOL) writeToCSVFile:(NSString *)csvFile atomically:(BOOL)atomically;`
+`-writeLineWithFields:` accepts an array of objects, sends each one to `-writeField:`, and then invokes `-writeLine`.
-All of the initializers (both class and instance versions) return an `NSArray` of `NSArray` objects.
+`-writeCommentLine:` accepts a string and writes it out to the file as a CSV-style comment.
-The `writeToCSVFile:` method expects the same structure (an `NSArray` of `NSArray` objects).
+In addition to writing to a file, `CHCSVWriter` can be initialized for writing directly to an `NSString`.
-There is also an `NSString` category to parse an `NSString` of CSV data into an `NSArray` of `NSArray` objects. This method is:
+Like `CHCSVParser`, `CHCSVWriter` can be customized with a delimiter other than `,` prior to beginning writing.
-- `- (NSArray *) CSVComponents;`
+###Convenience Methods
+Included in the code is an `NSArray` category to simplify reading from and writing to CSV files. In order to use these methods, you must include `CHCSVParser.*`, `CHCSVWriter.*`, and `NSArray+CHCSVAdditions.*` in your project (all six files). This category adds many methods to `NSArray` to simplify the process of converting a file, string, or input stream into an `NSArray` of `NSArrays` of `NSStrings`. There are also methods to write the array to a CSV file (or with a custom delimiter), or to convert it into an `NSString` of well-formed CSV.
-Both the `NSArray` and `NSString` categories require including the `CHCSVSupport.h` and `CHCSVSupport.m` files in your project.
+There is also an `NSString` category to parse an `NSString` of CSV data into an `NSArray` of `NSArray` objects. This method is `-[NSString CSVComponents]`.
###General Use
@@ -55,7 +54,6 @@ The simplest use of `CHCSVParser` is to include all of the files in your project
- `CHCSVWriter.h` and `CHCSVWriter.m`
- `NSArray+CHCSVAdditions.h` and `NSArray+CHCSVAdditions.m`
- `NSString+CHCSVAdditions.h` and `NSString+CHCSVAdditions.m`
-- `CHCSVSupport.h` and `CHCSVSupport.m`
Then to use any of the CSV parsing or writing functionality, simply `#import "CHCSV.h"` and use any of the classes and categories as you'd like.
@@ -63,7 +61,8 @@ Then to use any of the CSV parsing or writing functionality, simply `#import "CH
##Data Encoding
`CHCSVParser` relies on knowing the encoding of the CSV file. It should work with pretty much any kind of file encoding, if you can provide what that encoding is. If you do not know the encoding of the file, then `CHCSVParser` can make a naïve guess. `CHCSVParser` will try to guess the encoding of the file from among these options:
- - `NSUTF8StringEncoding` (the default/fallback encoding)
+ - `NSMacOSRomanStringEncoding` (the default/fallback encoding)
+ - `NSUTF8StringEncoding`
- `NSUTF16BigEndianStringEncoding`
- `NSUTF16LittleEndianStringEncoding`
- `NSUTF32BigEndianStringEncoding`
@@ -71,7 +70,10 @@ Then to use any of the CSV parsing or writing functionality, simply `#import "CH
##Performance
-`CHCSVParser` is conscious of low-memory environments, such as the iPhone or iPad. It can safely parse very large CSV files, because it only loads portions of the file into memory at a single time. For example, `CHCSVParser` can parse a 4 million line CSV file (over 300MB on disk) in under one second while only consuming about 75K of active memory.
+`CHCSVParser` is conscious of low-memory environments, such as the iPhone or iPad. It can safely parse very large CSV files, because it only loads portions of the file into memory at a single time.
+
+##To Do
+At some point, `CHCSVWriter` will support writing data directly to `NSOutputStream` instances.
##Credits
@@ -87,7 +89,7 @@ Then to use any of the CSV parsing or writing functionality, simply `#import "CH
`CHCSVParser` is licensed under the MIT license, which is reproduced in its entirety here:
->Copyright (c) 2010 Dave DeLong
+>Copyright (c) 2011 Dave DeLong
>
>Permission is hereby granted, free of charge, to any person obtaining a copy
>of this software and associated documentation files (the "Software"), to deal
View
7 main.m
@@ -30,7 +30,7 @@ - (void) parser:(CHCSVParser *)parser didFailWithError:(NSError *)error {
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString * file = @"/Users/dave/Developer/Open Source/Git Projects/CHCSVParser/Test.csv";
-
+
/**
CHCSVWriter *big = [[CHCSVWriter alloc] initWithCSVFile:file atomic:NO];
for (int i = 0; i < 1000000; ++i) {
@@ -70,7 +70,9 @@ int main (int argc, const char * argv[]) {
NSLog(@"Beginning...");
NSStringEncoding encoding = 0;
- CHCSVParser * p = [[CHCSVParser alloc] initWithContentsOfCSVFile:file usedEncoding:&encoding error:nil];
+ NSInputStream *stream = [NSInputStream inputStreamWithFileAtPath:file];
+ NSError *error = nil;
+ CHCSVParser * p = [[CHCSVParser alloc] initWithStream:stream usedEncoding:&encoding error:&error];
NSLog(@"encoding: %@", CFStringGetNameOfEncoding(CFStringConvertNSStringEncodingToEncoding(encoding)));
@@ -87,6 +89,7 @@ int main (int argc, const char * argv[]) {
NSArray *a = [NSArray arrayWithContentsOfCSVFile:file encoding:encoding error:nil];
+ NSLog(@"%@", a);
NSString *s = [a CSVString];
NSLog(@"%@", s);
Please sign in to comment.
Something went wrong with that request. Please try again.