加快将大量JSON数据写入磁盘

时间:2014-04-15 15:50:34

标签: ios objective-c json core-data file-io

我有一个可能基本调用的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

});

1 个答案:

答案 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()
  }
}