0

我有很多行需要插入到数据库中。我下载了大约 50 个以制表符分隔的 .txt 文件,其中包含我需要的信息。我解析数据并以相同的方法将其插入数据库。当我将它作为单独的方法使用时,我的 27" iMac 上的模拟器会因为内存不足而崩溃。该方法如下所示:

- (BOOL)insertDataWithFileName:(NSString *)fileName {
    NSLog(@"%s %@", __FUNCTION__, fileName);
    if (_db == nil) {
        return NO;
    }
    // Get the data from the file
    NSData *data = [[NSData alloc] initWithContentsOfFile:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:fileName]];
    NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    // Parse each line by newlines first
    NSArray *lines = [responseString componentsSeparatedByString:@"\n"];        

    NSString *ID = [[fileName componentsSeparatedByString:@"."] objectAtIndex:0];

    // Set up the database insert statement
    NSString *tableName = @"Hardcodedtablename"; // remove after prototype
    BOOL oldshouldcachestatements = _db.shouldCacheStatements;
    [_db setShouldCacheStatements:YES];
    [_db beginTransaction];
    NSString *insertQuery = [NSString stringWithFormat:@"INSERT INTO %@ values(null, ?, ?, ?, ?, ?, ?, ?);", tableName];
    BOOL success;

    // Parse each line by tabs
    for (NSString *line in lines) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSArray *fields = [line componentsSeparatedByString:@"\t"];

        // Need to check since some of the .txt files have an empty newline at the EOF.
        if ([fields count] == NUM_VARIANT_FIELDS) {
            NSNumber *loc = [NSNumber numberWithInteger:[[fields objectAtIndex:0] integerValue]];       
            NSString *carType = [fields objectAtIndex:1];
            NSString *model = [fields objectAtIndex:2];
            NSString *AA = [fields objectAtIndex:7];
            NSString *BB = [fields objectAtIndex:8];

            NSNumber *freq = [[fields objectAtIndex:11] isEqualToString:@""] ? [NSNumber numberWithDouble:-1.0] : [NSNumber numberWithDouble:[[fields objectAtIndex:11] doubleValue]];

            NSArray *argArray = [[NSArray alloc] initWithObjects:ID, loc, carType, model, AA, BB, freq, nil];

            success = [_db executeUpdate:insertQuery withArgumentsInArray:argArray];
            [argArray release];

        }
        [pool drain];
    }

    [_patientAnnotatedDatabase commit];
    [_patientAnnotatedDatabase setShouldCacheStatements:oldshouldcachestatements];

    return success;
}

正如您从我的 for 循环中看到的那样,在数组中的所有文件被 \t 分隔后,我实际上并不需要它。我设置了一个自动释放池来减少 for 循环中的内存占用。最大的文件中有 270,000 行。这些文件大约有 50 个。因此,在设备上的 2 个文件之后,它崩溃了。虽然没有错误消息。

我想知道此时我的选择是什么。iPad 真的可以处理这么多的数据吗?我可以对这种方法进行优化吗?

还是我必须在服务器端创建一个数据库并将数据库下载到设备上?如果我确实将数据库从服务器下载到设备,FMDB 是否支持将这些表从一个数据库传输到另一个数据库?我在谷歌搜索时找不到类似的东西。谢谢!

4

2 回答 2

0

这实际上取决于您使用数据的目的。如果您使用它来搜索或用于某些您真正需要所有这些的目的,那么您基本上使用了这么多内存:

270,000 rows * 25 chars/row * 50 files * 1 byte/char = 321 Mb of RAM

我猜测 25 chars/row 部分,但是当您使用超过 100 Mb 的内存时,您正在使用大量内存。但是,iPad确实有大约 1GB 的 RAM 供您使用,因此您似乎在可用内存量之内。但是,由于您使用 NSArrays 和 SQLite FMDB 来存储它(以及其他 NSObjects),当添加到 iPad 上运行的其他进程时,封装的数据可能超过 1GB。

所以,所有这些内存可能都是你的问题。您可能最好将所有这些数据保存在可以处理它的网络服务器上,并通过所述服务器调用您想要的任何功能。它可能会快得多,并且如果需要更新,它可以让您轻松地对数据进行调整。它还可以让您的应用程序在没有足够 RAM 的 iPhone 等设备上使用。

如果大量数据是您的问题,那么您的解决方案就是上述解决方案。但是,我仍然相信 iPad 能够处理 300+ Mb 的 RAM,因此您的问题可能出在代码上。确保您正确访问所有数据,尤其是当您将数据与文件分离为数组时,因为最小的“越界”数组错误可能会导致您的程序失败。

您是否也尝试过在启用内存分析器的情况下运行代码。您可以通过按住“运行”圆形按钮在新的 Xcode 中启用此应用程序,直到您可以选择“Profiler”选项。这个应用程序将显示您的应用程序正在使用多少内存,因此您可以确保它低于 1GB。

于 2012-07-23T00:47:41.810 回答
0

不幸的是,我在我的计划中设置了 NSZombieEnabled 以追踪早期的错误。关闭它后,它现在似乎没有在这一刻崩溃。

于 2012-07-23T19:41:08.303 回答