Ios 用于写入较大CSV文件的CHCSVWriter内存使用情况
我希望在将数据写入CSV文件时尽量减少内存使用 对于较大的表,它使用更多的内存,即使是临时的 有人能建议如何减少内存使用吗 也许我可以为更大的表分离操作,编写更多的文件,然后合并它们,但我还没有尝试,也许我遗漏了一些明显的东西 以下是当前使用的代码:Ios 用于写入较大CSV文件的CHCSVWriter内存使用情况,ios,objective-c,csv,memory-management,nsoutputstream,Ios,Objective C,Csv,Memory Management,Nsoutputstream,我希望在将数据写入CSV文件时尽量减少内存使用 对于较大的表,它使用更多的内存,即使是临时的 有人能建议如何减少内存使用吗 也许我可以为更大的表分离操作,编写更多的文件,然后合并它们,但我还没有尝试,也许我遗漏了一些明显的东西 以下是当前使用的代码: @autoreleasepool { NSOutputStream *csvStream = [[NSOutputStream alloc] initToMemory]; [csvStream open]; CHCSVW
@autoreleasepool {
NSOutputStream *csvStream = [[NSOutputStream alloc] initToMemory];
[csvStream open];
CHCSVWriter *writer = [[CHCSVWriter alloc] initWithOutputStream:csvStream encoding:NSUTF8StringEncoding delimiter:';'];
NSArray *keySortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES]];
if (writeHeader==YES) {
//> write header
NSMutableDictionary *firstRow = [[self sharedUploadManager].modifiedRows firstObject];
if (firstRow==nil) {
result = NO;
return result;
}
NSArray *orderedKeys = [[firstRow allKeys] sortedArrayUsingDescriptors:keySortDescriptors];
for (NSString *columnName in orderedKeys) {
[writer writeField:columnName];
}
}
[writer finishLine];
@autoreleasepool {
//> write the rows
for (NSMutableDictionary *row in [self sharedUploadManager].modifiedRows) {
NSArray *orderedKeys = [[row allKeys] sortedArrayUsingDescriptors:keySortDescriptors];
for (NSString *key in orderedKeys ) {
NSString *field = [row objectForKey:key];
if ([field isKindOfClass:[NSNull class]]) {
[writer writeField:nil];
} else {
[writer writeField:field];
}
}
//> finish the line
[writer finishLine];
}
}
[writer closeStream];
NSData *buffer = [csvStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
NSString *output = [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding];
if (![[NSFileManager defaultManager] fileExistsAtPath:csvPath]) {
[[NSFileManager defaultManager] createFileAtPath:csvPath contents:nil attributes:nil];
}
BOOL res = [[output dataUsingEncoding:NSUTF8StringEncoding] writeToFile:csvPath atomically:NO];
if (!res) {
NSLog(@"Error Creating CSV File path = %@", csvPath);
} else{
NSLog(@"Data saved! File path = %@", csvPath);
}
}
我以前也尝试过这种逻辑——稍微干净一点,但结果相同:
NSOutputStream *csvStream = [[NSOutputStream alloc] initToFileAtPath:csvPath append:YES];
[csvStream open];
CHCSVWriter *writer = [[CHCSVWriter alloc] initWithOutputStream:csvStream encoding:NSUTF8StringEncoding delimiter:';'];
if (writeHeader==YES) {
//> write header
NSMutableDictionary *firstRow = [rows firstObject];
if (firstRow==nil) {
result = NO;
return result;
}
NSArray *orderedKeys = [[firstRow allKeys] sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES]]];
for (NSString *columnName in orderedKeys) {
[writer writeField:columnName];
}
[writer finishLine];
}
//> write the rows
for (NSMutableDictionary *row in rows) {
NSArray *orderedKeys = [[row allKeys] sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES]]];
for (NSString *key in orderedKeys ) {
NSString *field = [row objectForKey:key];
if ([field isKindOfClass:[NSNull class]]) {
[writer writeField:nil];
}
else {
[writer writeField:field];
}
}
//> finish the line
[writer finishLine];
}
[writer closeStream];
如果您不想在创建大型CSV文件时使用大量内存,请不要创建基于内存的输出流。创建实际文件的输出流。然后CSV数据将写入文件而不是内存。然后文件可以是千兆字节,并且使用很少的内存 这样做的另一个好处是不需要访问缓冲区数据,从中创建字符串(现在是内存使用量的两倍),然后将字符串写入文件
NSOutputStream *csvStream = [NSOutputStream outputStreamToFileAtPath:csvPath append:NO];
[csvStream open];
CHCSVWriter *writer = [[CHCSVWriter alloc] initWithOutputStream:csvStream encoding:NSUTF8StringEncoding delimiter:';'];
// write your CSV entries
[writer closeStream];
就这样。创建该文件不需要其他代码
除了这些更改之外,您还需要更改使用自动释放池的位置。它应该位于外部for
循环的内部
//> write the rows
for (NSMutableDictionary *row in [self sharedUploadManager].modifiedRows) {
@autoreleasepool {
NSArray *orderedKeys = [[row allKeys] sortedArrayUsingDescriptors:keySortDescriptors];
for (NSString *key in orderedKeys ) {
NSString *field = [row objectForKey:key];
if ([field isKindOfClass:[NSNull class]]) {
[writer writeField:nil];
} else {
[writer writeField:field];
}
}
//> finish the line
[writer finishLine];
}
}
这将确保自动删除对象的内存在每一行之后都被清除。您好,谢谢您的回答,但我实际上也尝试过,对于更大的文件,这段代码仍在不断增长,发布只是为了看看是否有不同的工作方式。。。我可以看到,在调试会话期间以及使用分配工具时,分配不断增加。对于分配来说,writeField似乎消耗了很多,因此应用程序崩溃了近百万行。对于应用程序来说,这不是一种常见的情况,但可能有一天我会尝试处理它。@maddy我刚刚注意到你的逻辑没有使用append,我会尝试看看会发生什么。不,还是一样的。。。文件本身并没有那么大,似乎有漏洞,但我检测不到。。。最大的文件大约是20MB。谢谢,我在这里为这两个循环都这么做了(修改过的对象也可以很大),现在看起来更好了,但内存仍然增加。