Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to generate NSData object with random bytes of a specific length?

If I create a new NSData object of a specific size using dataWithBytes:length:, what is the most efficient way to create the input bytes (20 Mb worth) of random characters, preferably without reading the data in from a file? I need a unique buffer of a specific size each time.

Thanks

like image 312
Bama91 Avatar asked Feb 07 '11 04:02

Bama91


4 Answers

You can create a 20*2^20b NSData object, then append a random 4 byte integer to it 20*2^20/4 times with arc4random(). I believe you need to include stdlib.h (via Generating random numbers in 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;
}
like image 188
Thomson Comer Avatar answered Nov 15 '22 18:11

Thomson Comer


void * bytes = malloc(numberOfBytes);
NSData * data = [NSData dataWithBytes:bytes length:numberOfBytes];
free(bytes);

The bytes are not 'random', but will contain garbage values (whatever was on the heap before this was run). The advantage being its fast and the code is concise.

like image 44
Robert Avatar answered Nov 15 '22 19:11

Robert


Here's a 3-liner swift version:

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)
like image 28
ldiqual Avatar answered Nov 15 '22 17:11

ldiqual


You might consider using CCRandomGenerateBytes function from CommonCrypto to generate random data. Like:

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)
}
like image 21
sgl0v Avatar answered Nov 15 '22 19:11

sgl0v