Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 用于写入较大CSV文件的CHCSVWriter内存使用情况_Ios_Objective C_Csv_Memory Management_Nsoutputstream - Fatal编程技术网

Ios 用于写入较大CSV文件的CHCSVWriter内存使用情况

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

我希望在将数据写入CSV文件时尽量减少内存使用

对于较大的表,它使用更多的内存,即使是临时的

有人能建议如何减少内存使用吗

也许我可以为更大的表分离操作,编写更多的文件,然后合并它们,但我还没有尝试,也许我遗漏了一些明显的东西

以下是当前使用的代码:

 @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。谢谢,我在这里为这两个循环都这么做了(修改过的对象也可以很大),现在看起来更好了,但内存仍然增加。