生成具有特定长度的随机字节的 NSData 对象的最佳方法?

问题描述 投票:0回答:9

如果我使用 dataWithBytes:length: 创建一个特定大小的新 NSData 对象,创建随机字符的输入字节(20 Mb 值)的最有效方法是什么,最好不从文件中读取数据? 我每次都需要一个特定大小的唯一缓冲区。

谢谢

iphone objective-c c nsdata
9个回答
25
投票

您可以创建一个 20*2^20b

NSData
对象,然后使用
arc4random()
向其附加一个随机 4 字节整数 20*2^20/4 次。 我相信你需要包括
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;
}

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

这些字节不是“随机”的,但将包含垃圾值(无论运行之前堆上有什么)。 优点是速度快,代码简洁。


16
投票

这是 3 行 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))

斯威夫特3

let bytes = [UInt32](repeating: 0, count: length).map { _ in arc4random() }
let data = Data(bytes: bytes, count: length)

8
投票

您可以考虑使用

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)
}

6
投票

斯威夫特 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
}

Swift 5 更新:

func randomBytes(length: Int) -> Data? {
    var data = Data(count: length)
    let result = data.withUnsafeMutableBytes {
        SecRandomCopyBytes(kSecRandomDefault, length, $0.baseAddress!)
    }
    guard result == errSecSuccess else {
        return nil
    }
    return data
}

感谢这个帖子。


5
投票

使用

arc4random_buf
用随机字节填充缓冲区

Obj-C
+ (nullable NSData *)randomDataOfSize:(size_t)sizeInBytes
{
    void *buff = malloc(sizeInBytes);
    if (buff == NULL) {
        return nil;
    }
    arc4random_buf(buff, sizeInBytes);
    
    return [NSData dataWithBytesNoCopy:buff length:sizeInBytes freeWhenDone:YES];
}

2
投票

原始版本有一个错误,但我的版本解决了这个问题,希望不会引入任何新的错误。 希望有帮助。

- (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
投票

urandom 更高效。

这里是生成随机缓冲区的类别:

@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

0
投票

我已经在 github 上开源了我的 JFRandom 类,它可以做到这一点。 这是一篇博客文章,演示如何获取/使用它来实现您的目标...

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

© www.soinside.com 2019 - 2024. All rights reserved.