JP *_*sek 6 csv sqlite core-data ios
结论
问题已经结束,我想.
看起来问题与方法无关,但是XCode没有在构建之间正确地清理项目.
看起来在所有这些测试之后,正在使用的sqlite文件仍然是第一个没有编入索引的文件......
谨防XCode 4.3.2,我没有任何问题但是Clean没有清理,或者添加文件到项目不会自动添加到捆绑资源...
感谢您的答案不同..
更新3
由于我邀请任何人尝试相同的步骤来查看它们是否得到相同的结果,让我详细说明我做了什么:
我从空白项目开始
我定义了一个带有一个实体的数据模型,3个属性(2个字符串,1个浮点数)
第一个字符串已编入索引
在doneLaunchingWithOptions中,我打电话给:
[self performSelectorInBackground:@selector(populateDB) withObject:nil];
Run Code Online (Sandbox Code Playgroud)
populateDb的代码如下:
-(void)populateDB{
NSLog(@"start");
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
NSManagedObjectContext *context;
if (coordinator != nil) {
context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:coordinator];
}
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"input" ofType:@"txt"];
if (filePath) {
NSString * myText = [[NSString alloc]
initWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:nil];
if (myText) {
__block int count = 0;
[myText enumerateLinesUsingBlock:^(NSString * line, BOOL * stop) {
line=[line stringByReplacingOccurrencesOfString:@"\t" withString:@" "];
NSArray *lineComponents=[line componentsSeparatedByString:@" "];
if(lineComponents){
if([lineComponents count]==3){
float f=[[lineComponents objectAtIndex:0] floatValue];
NSNumber *number=[NSNumber numberWithFloat:f];
NSString *string1=[lineComponents objectAtIndex:1];
NSString *string2=[lineComponents objectAtIndex:2];
NSManagedObject *object=[NSEntityDescription insertNewObjectForEntityForName:@"Bigram" inManagedObjectContext:context];
[object setValue:number forKey:@"number"];
[object setValue:string1 forKey:@"string1"];
[object setValue:string2 forKey:@"string2"];
NSError *error;
count++;
if(count>=1000){
if (![context save:&error]) {
NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
count=0;
}
}
}
}];
NSLog(@"done importing");
NSError *error;
if (![context save:&error]) {
NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
}
}
NSLog(@"end");
}
Run Code Online (Sandbox Code Playgroud)
其他一切都是默认的核心数据代码,没有添加.
我在模拟器中运行它.
我去〜/ Library/Application Support/iPhone Simulator/5.1/Applications // Documents
有生成的sqlite文件,
我把它复制到我的包中
我注释掉对populateDb的调用
我编辑persistentStoreCoordinator来复制第一次运行时从包到文档的sqlite文件
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
@synchronized (self)
{
if (__persistentStoreCoordinator != nil)
return __persistentStoreCoordinator;
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"myProject" ofType:@"sqlite"];
NSString *storePath = [[[self applicationDocumentsDirectory] path] stringByAppendingPathComponent: @"myProject.sqlite"];
NSError *error;
if (![[NSFileManager defaultManager] fileExistsAtPath:storePath])
{
if ([[NSFileManager defaultManager] copyItemAtPath:defaultStorePath toPath:storePath error:&error])
NSLog(@"Copied starting data to %@", storePath);
else
NSLog(@"Error copying default DB to %@ (%@)", storePath, error);
}
NSURL *storeURL = [NSURL fileURLWithPath:storePath];
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
}
Run Code Online (Sandbox Code Playgroud)
我从模拟器中删除了应用程序,我检查〜/ Library/Application Support/iPhone Simulator/5.1/Applications /现在已删除
我重建并再次启动
正如预期的那样,将sqlite文件复制到〜/ Library/Application Support/iPhone模拟器/ 5.1 /应用程序//文档
但是,文件的大小明显小于捆绑包中的大小!
另外,使用类似谓词的谓词进行简单查询= [NSPredicate predicateWithFormat:@"string1 ==%@",string1]; 清楚地表明string1不再被索引了
之后,我创建了一个新版本的datamodel,带有无意义的更新,只是为了强制轻量级迁移
如果在模拟器上运行,迁移需要几秒钟,数据库的大小翻倍,相同的查询现在需要不到一秒的时间而不是分钟.
这将解决我的问题,强制迁移,但同样的迁移需要3分钟在iPad上并发生在前台.
所以我现在所处的位置,对我来说最好的解决方案仍然是防止索引被删除,在启动时任何其他导入解决方案只需要花费太多时间.
如果您需要更多说明,请告诉我......
更新2
因此,到目前为止,我所获得的最佳结果是使用具有类似数据模型的快速工具生成的sqlite文件来播种核心数据数据库,但在生成sqlite文件时没有设置索引.然后,我在核心数据应用程序中导入此sqlite文件并设置索引,并允许轻量级迁移.在新iPad上有2百万的记录,这次迁移还需要3分钟.最终的应用程序应该有这个记录数的5倍,所以我们仍然需要很长的处理时间.如果我走这条路,那么新问题就是:可以在后台执行轻量级迁移吗?
更新
我的问题不是如何创建一个工具来填充Core Data数据库,然后将sqlite文件导入我的应用程序.
我知道怎么做,我做了无数次.
但到目前为止,我还没有意识到这种方法会产生一些副作用:在我的情况下,结果数据库中的索引属性在导入sqlite文件时显然得到了"无索引".
如果您能够验证任何索引数据在转移后仍然被编入索引,我有兴趣知道您如何继续,或者以其他方式有效地为这样的数据库提供种子的最佳策略.
原版的
我有一个大的CSV文件(数百万行),包含4列,字符串和浮点数.这适用于iOS应用.
我需要在第一次加载应用程序时将其加载到核心数据中.
在数据可用之前,应用程序几乎不起作用,因此加载时间很重要,因为第一次用户显然不希望应用程序在运行之前需要20分钟才能加载.
现在,我目前的代码在新iPad上花了20分钟来处理一个200万行的csv文件.
我使用背景上下文来不锁定UI,并且每1,000条记录保存上下文
我的第一个想法是在模拟器上生成数据库,然后在首次启动时将其复制/粘贴到文档文件夹中,因为这是播种大型数据库的常见非官方方式.不幸的是,索引似乎没有在这样的传输中存活,虽然数据库在几秒钟之后就可用,但性能很糟糕,因为我的索引丢失了.我已经发布了一个关于索引的问题,但似乎没有一个好的答案.
所以我要找的是:
使用在Cocoa上编写的脱机应用程序(比如命令行实用程序)预生成数据库,该应用程序在OS X上运行,并使用与iOS相同的Core Data框架.您无需担心"索引幸存"或其他任何内容 - 输出是Core Data生成的.sqlite数据库文件,可直接立即供iOS应用程序使用.
只要您可以脱机执行数据库生成,它就是迄今为止最好的解决方案.我已成功使用此技术自行预生成数据库以进行iOS部署.查看我之前的问题/答案以获取更多细节.