Best way to generate NSData object with random byt

2019-03-15 07:27发布

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

9条回答
2楼-- · 2019-03-15 07:38

The original version has a bug but mine takes care of that and hopefully doesn't introduce any new one. Hope it helps.

- (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;
}

Here is its unit test:

NSInteger givenLength = INT16_MAX;
NSData *randomData = [self randomDataWithBytes: givenLength];
STAssertTrue([randomData length] == givenLength,
             @"RandomDataWithBytes Failed Expected size %d and got %d", 
             givenLength, [randomData length]);
查看更多
Root(大扎)
3楼-- · 2019-03-15 07:40

I've open sourced my JFRandom class over at github which can do exactly this. Here's a blog post demonstrating how to obtain/use it to achieve your goal...

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

查看更多
Summer. ? 凉城
4楼-- · 2019-03-15 07:42

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;
}
查看更多
Evening l夕情丶
5楼-- · 2019-03-15 07:48

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)
查看更多
看我几分像从前
6楼-- · 2019-03-15 07:55
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.

查看更多
一夜七次
7楼-- · 2019-03-15 07:57

Use arc4random_buf to fill the buffer with random bytes

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];
}
查看更多
登录 后发表回答