Лучший способ создать объект NSData со случайными байтами определенной длины? - PullRequest
16 голосов
/ 07 февраля 2011

Если я создаю новый объект NSData определенного размера, используя dataWithBytes: length:, каков наиболее эффективный способ создания входных байтов (стоимостью 20 МБ) случайных символов, предпочтительно без чтения данных из файла?Каждый раз мне нужен уникальный буфер определенного размера.

Спасибо

Ответы [ 9 ]

21 голосов
/ 07 февраля 2011

Вы можете создать объект 20 * 2 ^ 20b NSData, а затем добавить к нему случайное 4-байтовое целое число 20 * 2 ^ 20/4 раза с помощью arc4random(). Я считаю, что вам нужно включить stdlib.h (через Генерация случайных чисел в Objective-C ).

#include <stdlib.h>

-(NSData*)create20mbRandomNSData
{
  int twentyMb           = 20971520;
  NSMutableData* theData = [NSMutableData dataWithCapacity:twentyMb];
  for( unsigned int i = 0 ; i < twentyMb/4 ; ++i )
  { 
    u_int32_t randomBits = arc4random();
    [theData appendBytes:(void*)&randomBits length:4];
  }
  return theData;
}
19 голосов
/ 10 июля 2013
void * bytes = malloc(numberOfBytes);
NSData * data = [NSData dataWithBytes:bytes length:numberOfBytes];
free(bytes);

Байты не являются «случайными», но будут содержать значения мусора (все, что было в куче до того, как это было выполнено) Преимущество в том, что он быстрый, а код лаконичный.

13 голосов
/ 02 апреля 2016

Вот 3-х строчная версия swift:

Swift 2

let length = 2048
let bytes = [UInt32](count: length, repeatedValue: 0).map { _ in arc4random() }
let data = NSData(bytes: bytes, length: bytes.count * sizeof(UInt32))

Swift 3

let bytes = [UInt32](repeating: 0, count: length).map { _ in arc4random() }
let data = Data(bytes: bytes, count: length)
6 голосов
/ 12 мая 2016

Вы можете рассмотреть возможность использования функции CCRandomGenerateBytes из CommonCrypto для генерации случайных данных. Как:

func generateBytes(length : Int) throws -> NSData? {
    var bytes = [UInt8](count: length, repeatedValue: UInt8(0))
    let statusCode = CCRandomGenerateBytes(&bytes, bytes.count)
    if statusCode != CCRNGStatus(kCCSuccess) {
        return nil
    }
    return NSData(bytes: bytes, length: bytes.count)
}
2 голосов
/ 11 октября 2016

Свифт 3:

import Security

func randomBytes(length: Int) -> Data {
    var data = Data(capacity: length)
    data.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<UInt8>) -> Void in
        let _ = SecRandomCopyBytes(kSecRandomDefault, length, bytes)
    }
    return data
}
1 голос
/ 27 июля 2011

В оригинальной версии есть ошибка, но моя позаботится об этом и, надеюсь, не представит новую.Надеюсь, это поможет.

- (NSData *)randomDataWithBytes: (NSUInteger)length {
    NSMutableData *mutableData = [NSMutableData dataWithCapacity: length];
    for (unsigned int i = 0; i < size; i++) { 
        NSInteger randomBits = arc4random();
        [mutableData appendBytes: (void *) &randomBits length: 1];
    } return mutableData;
}

Вот его модульный тест:

NSInteger givenLength = INT16_MAX;
NSData *randomData = [self randomDataWithBytes: givenLength];
STAssertTrue([randomData length] == givenLength,
             @"RandomDataWithBytes Failed Expected size %d and got %d", 
             givenLength, [randomData length]);
0 голосов
/ 11 декабря 2018

Используйте arc4random_buf для заполнения буфера случайными байтами

Obj-C

+ (nullable NSData *)radomDataOfSize:(size_t)sizeInBytes
{
    void *buff = malloc(sizeInBytes);
    if (buff == NULL) {
        return nil;
    }
    arc4random_buf(buff, sizeInBytes);

    return [NSData dataWithBytesNoCopy:buff length:sizeInBytes freeWhenDone:YES];
}
0 голосов
/ 15 мая 2012

Я открыл свой класс JFRandom в github, который может сделать именно это. Вот сообщение в блоге, демонстрирующее, как получить / использовать его для достижения своей цели ...

http://jayfuerstenberg.com/devblog/generating-random-numbers-strings-and-data-in-objective-c

0 голосов
/ 08 декабря 2011

Урандом более эффективен.

Вот категория для генерации случайных буферов:

@interface NSMutableData(Random)
+(id)randomDataWithLength:(NSUInteger)length;
@end

@implementation NSMutableData(Random)
+(id)randomDataWithLength:(NSUInteger)length
{
    NSMutableData* data=[NSMutableData dataWithLength:length];
    [[NSInputStream inputStreamWithFileAtPath:@"/dev/urandom"] read:(uint8_t*)[data mutableBytes] maxLength:length];
    return data;
}
@end
...