在Swift中将NSData转换为[Uint8]


74

我无法在Swift中找到解决这个问题的方法(它们都是Objective-C,并且它们处理的指针在Swift中我认为并不以相同的形式存在)。有什么办法可以将NSData对象转换为[Uint8]Swift形式的字节数组?

Answers:


116

如果以稍微复杂的方式遍历指针,或者通过ArraySwift 3中引入的新构造函数,则可以避免先将数组初始化为占位符值。

迅捷3

let data = "foo".data(using: .utf8)!

// new constructor:
let array = [UInt8](data)

// …or old style through pointers:
let array = data.withUnsafeBytes {
    [UInt8](UnsafeBufferPointer(start: $0, count: data.count))
}

迅捷2

Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>(data.bytes), count: data.length))

2
@califrench对不起,我没有关注。1)没有NSArray我能发现的东西,bytes访问器不会返回它。2)它将导致什么错误?如果您指的是NS*类的可能不可用,请记住该问题指定NSData
阿库(Arkku),2016年

1
对不起,@ Arkku,我很困惑,我想了一会儿要Array()依靠,NSArray但我不认为这是...自NSArrays以来,问题一直在尝试使用下标访问元素不知道它们包含哪种元素,而Swift却知道Array
califrench

1
@Dan在Swift 2.2和Swift 3中对我来说都很好。在Swift 3中,前一行是let data : NSData! = "foo".data(using: String.Encoding.utf8)
Arkku,2016年

1
@Arkku,它没有使用最新的Swift进行编译,我不得不将其更改为:array = data.withUnsafeBytes {Array中的字节(UnsafeBufferPointer(start:bytes,count:data.count))}
Zmey 2016年

1
@LeoDabus这基本上是一种不同的说法[UInt8](data),自从最新的编辑以来,它已经在答案中了。(还有IMO带有显式类型的更清晰的语法。)
Arkku

46

这很有趣,但是存在更简单的解决方案。可以在Swift 3中使用。我今天用过这个。

data: Data // as function parameter    
let byteArray = [UInt8](data)

就这样!:) NSData可以轻松桥接到Data。

更新:(由于安德鲁·科斯特评论)

Swift 4.1,Xcode 9.3.1

刚刚经过重新检查-一切正常。

if let nsData = NSData(base64Encoded: "VGVzdFN0cmluZw==", options: .ignoreUnknownCharacters) {
let bytes = [UInt8](nsData as Data)
print(bytes, String(bytes: bytes, encoding: .utf8))

输出: [84、101、115、116、83、116、114、105、110、103]可选(“ TestString”)


1
既然Swift 3已经发布,这应该是公认的解决方案。
ChrisB

这很可能会复制您的数据。虽然很小,但没什么大不了的。如果很大,会引起很多问题。
路加福音

@AndrewKoster请看我的更新。或提供详细说明
-sVd

看起来现在可以使用了。我不知道编译器是否更改,或者您的答案是否更改,但是可以编译。
安德鲁·科斯特

1
@AndrewKoster是的,您确实知道:检查答案的编辑历史记录。原始答案未更改,仅添加了更新。(就我的回答而言,您发表了相同的评论:它在2016年至今尚未进行过编辑。)当然,您应该知道是否更新了编译器。但是,鉴于答案已经在官方发行版中使用了两年了,所以我认为您以前尝试过的其他问题很有可能被破坏了。无论如何,答案无法预测未来,因此我质疑是否赞成“不再有效”。
Arkku

41

Swift 5解决方案

资料至[位元组]

extension Data {
    var bytes : [UInt8]{
        return [UInt8](self)
    }
}

[bytes]至数据

extension Array where Element == UInt8 {
    var data : Data{
        return Data(self)
    }
}

1
在Swift 5中不推荐使用data(bytes:(self)):'(
vmeyer

很好的答案,优雅的非洲
伍德斯托克

抱歉,这是一个愚蠢的问题,但这会产生副本,对吗?
Tobi Schweiger

22

您可以使用getBytes函数NSData获得等效的字节数组。

由于您未提供任何源代码,因此我将使用已转换为NSData的Swift String内容。

var string = "Hello World"
let data : NSData! = string.dataUsingEncoding(NSUTF8StringEncoding)

let count = data.length / sizeof(UInt8)

// create an array of Uint8
var array = [UInt8](count: count, repeatedValue: 0)

// copy bytes into array
data.getBytes(&array, length:count * sizeof(UInt8))

println(array)

迅捷3/4

let count = data.length / MemoryLayout<UInt8>.size

// create an array of Uint8
var byteArray = [UInt8](repeating: 0, count: count)
// copy bytes into array
data.getBytes(&byteArray, length:count)

3
对于快速3,用MemoryLayout <UInt8> .size替换sizeof(UInt8)
Marek H

3

迅捷3/4

let data = Data(bytes: [0x01, 0x02, 0x03])
let byteArray: [UInt8] = data.map { $0 }

0

你可以试试

extension Data {
func toByteArray() -> [UInt8]? {
    var byteData = [UInt8](repeating:0, count: self.count)
    self.copyBytes(to: &byteData, count: self.count)
    return byteData
  }
}

0

迅速4和图像数据到字节数组。

 func getArrayOfBytesFromImage(imageData:Data) ->[UInt8]{

    let count = imageData.count / MemoryLayout<UInt8>.size
    var byteArray = [UInt8](repeating: 0, count: count)
    imageData.copyBytes(to: &byteArray, count:count)
    return byteArray

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.