在objective-c中,将uint8_t数组写入二进制文件的有效方法是什么?

时间:2017-02-22 20:37:12

标签: objective-c

我有一个大的一维uint8_t数组,我无法找到一种有效的方法将它发送到二进制文件而不先将其转换为NSData。有没有一种更有效的方法将我的数组放入文件而不是先转换它?

谢谢, 戴尔

编辑:测试答案的代码(在viewDidLoad中),这也是直接从文件中读取到uint8_t ARRAY:

  filemgr= [NSFileManager defaultManager];
  dirPaths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  dataDir= dirPaths[0];
  NSLog(@"Data dir is %@",dataDir);
  dataPath = [NSString stringWithFormat:@"%@/junk.bin",dataDir];
  report_memory();
  [self read_file];
  report_memory();
  [filemgr removeItemAtPath: dataPath error: Nil]; //TODO remove after test
  if (![filemgr fileExistsAtPath:dataPath]){
     memset(ONOFFrecords,0xFF,8388608); //set all bytes of ONOFFrecords to 0xFF
     [[NSData data] writeToFile:dataPath atomically:YES]; //make empty file
    report_memory();
     double strt= CACurrentMediaTime();
     NSData* ONOFFdata = [NSData dataWithBytesNoCopy:&ONOFFrecords[0] length:sizeof(ONOFFrecords) freeWhenDone:NO];
     NSFileHandle *handle= [NSFileHandle fileHandleForWritingAtPath:dataPath];
     [handle seekToFileOffset:0];
     [handle writeData:ONOFFdata];
     [handle closeFile];
     NSLog(@"8 MB file of uint8_t's created and saved in %f secs to all 0xFF's", CACurrentMediaTime()-strt);
     report_memory();
  } else {
    report_memory();
    //lets read that file and put it in uint8_t ONOFFrecords
    [self read_file];
     report_memory();
  }
  //TODO remove below after test
  //lets read that file and put it in uint8_t ONOFFrecords
  report_memory();
  [self read_file];
  report_memory();
  //lets change some of that data
  ONOFFrecords[0] = 0x03;
  //and save write all data to the same file
  report_memory();
  double strt= CACurrentMediaTime();
  NSData *ONOFFdata = [NSData dataWithBytesNoCopy:&ONOFFrecords[0] length:sizeof(ONOFFrecords) freeWhenDone:NO];
  NSFileHandle *handle= [NSFileHandle fileHandleForWritingAtPath:dataPath];
  [handle seekToFileOffset:0];
  [handle writeData:ONOFFdata];
  [handle closeFile];
  NSLog(@"Updated 8 MB file of uint8_t's WRITE in %f secs with first uint8_t = %u", CACurrentMediaTime()-strt,ONOFFrecords[0]);
  report_memory();
  //lets read that file and put it in uint8_t ONOFFrecords
  report_memory();
  [self read_file];
  report_memory();

和read_file函数:

- (void) read_file
{
  NSInteger result;
  uint8_t buffer[4096];
  uint32_t pos = 0;
  uint8_t haderr = 0;
  double strt= CACurrentMediaTime();
  NSInputStream *iStream = [[NSInputStream alloc] initWithFileAtPath:dataPath];
  [iStream open];
  while ((result = [iStream read:buffer maxLength:4096]) != 0){
     if (result>0){
        memcpy(ONOFFrecords+pos, buffer, result);
        pos+=result;
     }else{
        haderr=1;
        NSLog(@"Error %@",[iStream streamError]);
        break;
     }
  }
  [iStream close];
  if (haderr==0){
     NSLog(@"8 MB file of uint8_t's READ in %f secs with first uint8_t = %u last pos %u", CACurrentMediaTime()-strt,ONOFFrecords[0],pos);
  }
}

和report_memory()函数(也需要#import):

#import <mach/mach.h>

// ...

void report_memory(void)
{
  struct mach_task_basic_info info;
  mach_msg_type_number_t size = MACH_TASK_BASIC_INFO_COUNT;
  kern_return_t kerr = task_info(mach_task_self(),
                                            MACH_TASK_BASIC_INFO,
                                            (task_info_t)&info,
                                            &size);
  if( kerr == KERN_SUCCESS ) {
     NSLog(@"Memory in use (in bytes): %llu", info.resident_size);
  } else {
     NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
  }
}

和输出:

2017-02-23 12:17:41.530929 HaloLog[2107:1026526] Data dir is /var/mobile/Containers/Data/Application/C448DBF6-5FF8-4272-BA57-6595D07AB6E5/Documents
2017-02-23 12:17:41.531127 HaloLog[2107:1026526] Memory in use (in bytes): 29302784
2017-02-23 12:17:41.532333 HaloLog[2107:1026526] Error Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory" UserInfo={_kCFStreamErrorCodeKey=2, _kCFStreamErrorDomainKey=1}
2017-02-23 12:17:41.532425 HaloLog[2107:1026526] Memory in use (in bytes): 29306880
2017-02-23 12:17:41.583930 HaloLog[2107:1026526] Memory in use (in bytes): 29392896
2017-02-23 12:17:41.604554 HaloLog[2107:1026526] 8 MB file of uint8_t's created and saved in 0.020386 secs to all 0xFF's
2017-02-23 12:17:41.604748 HaloLog[2107:1026526] Memory in use (in bytes): 29392896
2017-02-23 12:17:41.604899 HaloLog[2107:1026526] Memory in use (in bytes): 29392896
2017-02-23 12:17:41.635276 HaloLog[2107:1026526] 8 MB file of uint8_t's READ in 0.030260 secs with first uint8_t = 255 last pos 8388608
2017-02-23 12:17:41.635422 HaloLog[2107:1026526] Memory in use (in bytes): 29392896
2017-02-23 12:17:41.635460 HaloLog[2107:1026526] Memory in use (in bytes): 29392896
2017-02-23 12:17:41.652201 HaloLog[2107:1026526] Updated 8 MB file of uint8_t's WRITE in 0.016660 secs with first uint8_t = 3
2017-02-23 12:17:41.652303 HaloLog[2107:1026526] Memory in use (in bytes): 29392896
2017-02-23 12:17:41.652342 HaloLog[2107:1026526] Memory in use (in bytes): 29392896
2017-02-23 12:17:41.678894 HaloLog[2107:1026526] 8 MB file of uint8_t's READ in 0.026464 secs with first uint8_t = 3 last pos 8388608
2017-02-23 12:17:41.679007 HaloLog[2107:1026526] Memory in use (in bytes): 29392896
(lldb) 

1 个答案:

答案 0 :(得分:1)

您可以使用NSData的dataWithBytesNoCopy:length:freeWhenDone:。您将获得一个引用您的数据的NSData对象,但不会复制它。确保为NO传递freeWhenDone,否则,NSData对象将尝试释放您在解除分配时传入的字节,这可能是您不想要的。

uint8_t myArray[] = {
    0x01, 0x02, 0x03, 0x04, 0x05
};

NSData* theData = [NSData dataWithBytesNoCopy:&myArray[0]
                                       length:sizeof(myArray)
                                 freeWhenDone:NO];

然后使用任何方法撰写NSData,或许NSFileManagerNSFileHandle