2017-02-22 21 views
0

У меня есть большой одномерный массив uint8_t, и я не могу найти эффективный способ отправить его в двоичный файл без предварительной конвертации в NSData. Есть ли более эффективный способ получить мой массив в файл, чем преобразовать его в первую очередь?В объективе-c, эффективный способ записи массива uint8_t в двоичный файл?

Спасибо, Dale

EDIT: Тест код ответа (в 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) 
+0

Почему вы просто не используете C, чтобы справиться с этим? –

+0

Потому что я все еще новичок и делаю конверсию, это все, что я мог понять. Но мне кажется, что это неэффективно, потому что это 8 МБ. – KiloOne

+0

Вы хотите написать uints как целые числа (буквально текстовый файл с числами в нем)? – Prientus

ответ

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, возможно, NSFileManager или NSFileHandle.

+0

Спасибо, это именно то, что я просил. Не могли бы вы прокомментировать мой тестовый код, который я добавил в свой оригинальный пост? Правильно ли я использую его? Будут ли у меня проблемы с памятью, если я изменю данные массива и сохраню регулярно, как это было в моем тестовом коде? – KiloOne

+0

Кроме того, есть ли способ сделать это в «обратном», я имею в виду, читать данные из файла и поместить его прямо в мой массив uint8_t? – KiloOne