Лучший способ генерировать объект NSData со случайными байтами определенной длины?
Если я создаю новый объект NSData определенного размера, используя dataWithBytes: length:, то какой самый эффективный способ создать входные байты (20 Мб) случайных символов, желательно, не читая данные из файла? Мне нужен уникальный буфер определенного размера каждый раз.
Спасибо
Ответы
Ответ 1
Вы можете создать объект 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;
}
Ответ 2
void * bytes = malloc(numberOfBytes);
NSData * data = [NSData dataWithBytes:bytes length:numberOfBytes];
free(bytes);
Байты не являются "случайными", но будут содержать значения мусора (все, что было в куче до того, как это было запущено). Преимущество заключается в том, что он быстрый, а код сжатый.
Ответ 3
Здесь приведена 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))
Swift 3
let bytes = [UInt32](repeating: 0, count: length).map { _ in arc4random() }
let data = Data(bytes: bytes, count: length)
Ответ 4
Вы можете использовать функцию 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)
}
Ответ 5
В исходной версии есть ошибка, но моя позаботится об этом и, надеюсь, не представит никакой новой.
Надеюсь, что это поможет.
- (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;
}
Вот его 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]);
Ответ 6
Swift 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
}
Ответ 7
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
Ответ 8
Я открыл свой класс JFRandom в github, который может сделать именно это. Здесь сообщение в блоге, демонстрирующее, как получить/использовать его для достижения вашей цели...
http://jayfuerstenberg.com/devblog/generating-random-numbers-strings-and-data-in-objective-c
Ответ 9
Используйте 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];
}