我有一个可能基本调用的40k记录循环。似乎写入文件真的很慢。如果我通过循环迭代它几乎是瞬间,所以我意识到它不是核心数据迭代,文件编写过程很慢。有没有比我在这里做的更好的方法将数据流式传输到文件?
#ifndef jsonAppend
#define jsonAppend(X) [outStream write:[[X dataUsingEncoding:NSUTF8StringEncoding ] bytes] maxLength:[X lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]
#endif
NSOutputStream *outStream = [NSOutputStream outputStreamToFileAtPath:tempFilePath append:NO];
dispatch_async(backgroundQueue, ^{
// Open an output stream to write to.
[outStream open];
// Other code ... blablabla
for (AHRSMessage *msg in results)
{
@autoreleasepool
{
[NSJSONSerialization writeJSONObject:msg.attributesAsDictionary toStream:outStream options:0 error:&error];
jsonAppend(@",\n");
i++; // MessageCounter
// Update UI only sometimes
if (i % 100)
{
dispatch_async(dispatch_get_main_queue(), ^
{
@autoreleasepool {
float pct = i / recordCount ;
NSString *pctStr = [NSString stringWithFormat:@"%02.0f%%", pct * 100.0];
[[weakSelf percentLabel] setText:pctStr];
[[weakSelf parsingProgress] setProgress:pct animated:YES];
/* - Animate inner circle on units of 1% - */
int singPctMsgCount = recordCount / 100;
float fastParse = (i % singPctMsgCount) / (float)singPctMsgCount;
[[weakSelf fastParsingProgress] setProgress:fastParse animated:YES] ;
[weakSelf updateUI];
}
});
}
}
} // end for loop
});
答案 0 :(得分:1)
由于它只有18MB,只需将其序列化为NSMutableData
对象,然后将其写入磁盘。
那应该非常快。 NSMutableData
可以轻松处理甚至不适合闪存的大量数据(假设您有64位处理器),更不用说iOS设备上的RAM了。
像这样:
dispatch_async(backgroundQueue, ^{
NSMutableData *outData = [NSMutableData data];
// Other code ... blablabla
for (AHRSMessage *msg in results)
{
@autoreleasepool
{
[outData appendData:[NSJSONSerialization dataWithJSONObject:msg.attributesAsDictionary options:0 error:&error];
i++; // MessageCounter
// Update UI only sometimes
if (i % 100)
{
dispatch_async(dispatch_get_main_queue(), ^
{
@autoreleasepool {
... update progress bar ...
}
});
}
}
} // end for loop
[outData writeToURL:outURL atomically:YES];
});
另外,我不会使用if (i % 100)
来决定更新进度条的时间。相反,我会使用:
CFTimeInterval lastProgressUpdate = CACurrentMediaTime();
for ( ... ) {
...
if (CACurrentMediaTime() - lastProgressUpdate > 0.02) { // 1/60th of a second. Which is the refresh rate of most LCD screens
... update progress bar ....
lastProgressUpdate = CACurrentMediaTime()
}
}