在Swift中从字节数组获取NSData

40

我正在尝试从字节数组创建一个NSData var

在Obj-C中,我可能会这样做:

NSData *endMarker = [[NSData alloc] initWithBytes:{ 0xFF, 0xD9 }, length: 2]

我无法找到Swift中可行的等效方法。

6个回答

72

NSData有一个可以接受bytes指针的初始化器: init(bytes: UnsafeMutablePointer<Void>, length: Int)。一个UnsafePointer参数可以接受多种不同的东西,包括简单的Swift数组,因此你可以使用基本上和Objective-C相同的语法。当你传递数组时,需要确保将其标识为UInt8数组,否则Swift的类型推断会认为你要创建一个Int数组。

var endMarker = NSData(bytes: [0xFF, 0xD9] as [UInt8], length: 2)

你可以在苹果公司的与C API交互文档中了解有关不安全指针参数的更多信息。


那也是我原本的想法。但是当我在调试器中打印出来时,我得到的是:<ff00>;如果我再打印更多字节,我得到的仍然是相同的东西,在第一个字节之后都是00。 - Jeff
2
将类型信息添加到数组中 - 它发送的是一个 Int 数组而不是一个 Byte 数组。 - Nate Cook
仅作补充,Byte 在Swift1.2中已被删除,请使用UInt8代替。 - mash
我正在学习Swift,所以这可能是一个愚蠢的问题。如果我写下以下内容:“_fileHandle!.write(NSData(bytes:UnsafePointer(byteData),length:byteLength)as Data)”,那么它可以正常工作。但我担心这可能涉及创建byteData的新副本,而byteData是一个100 KB的字节数组。肯定不是吧? - RenniePet

19
var foo : Byte[] = [0xff, 0xD9]

var data = NSData(bytes: foo, length: foo.count)

println("\(data)")

输出: ff d9

var data = NSData(bytes: [0xFF, 0xD9] as Byte[], length: 2)

println("\(data)")

输出:ff d9

编辑:啊,你需要写成'as Byte[]',这样结果就一样了。


更新为Swift 2.2版

var foo:[UInt8] = [0xff, 0xD9]
var data = NSData(bytes: foo, length: foo.count)
print("\(data)")

输出: ff d9

var data = NSData(bytes: [0xFF, 0xD9] as [UInt8], length: 2)
print("\(data)")

输出: ff d9


2
看起来在Swift 1.2中不能再使用Byte了。取而代之的是,写成[Uint8]而不是Byte[] - Albert Vila Calvo
不,那是 UInt8 - Dan Rosenstark

19

在Swift 3中,您不需要扩展Data,可以这样做:

let bytes:[UInt8] = [0x00, 0x01, 0x02, 0x03]
let data = Data(bytes: bytes)
print(data as NSData)

打印“<00010203>”

再次获取字节数组:

let byteArray:[UInt8] = [UInt8](data)

谢谢。Swift 4 有什么变化吗? - meaning-matters

8

针对Swift 5,我已经创建了另一个Data扩展,它运行良好。

extension Data {

    init<T>(fromArray values: [T]) {
        var values = values
        self.init(buffer: UnsafeBufferPointer(start: &values, count: values.count))
    }

    func toArray<T>(type: T.Type) -> [T] {
        let value = self.withUnsafeBytes {
            $0.baseAddress?.assumingMemoryBound(to: T.self)
        }
        return [T](UnsafeBufferPointer(start: value, count: self.count / MemoryLayout<T>.stride))
    }

}

示例用法

let data = Data(fromArray: [1, 2, 3, 4, 5])
let array = data.toArray(type: Int.self)
print(array)
// [1, 2, 3, 4, 5]

6

Swift 3 extension

extension Data {

    init<T>(fromArray values: [T]) {
        var values = values
        self.init(buffer: UnsafeBufferPointer(start: &values, count: values.count))
    }

    func toArray<T>(type: T.Type) -> [T] {
        return self.withUnsafeBytes {
            [T](UnsafeBufferPointer(start: $0, count: self.count/MemoryLayout<T>.stride))
        }
    }
}

使用方法

let bytes:[UInt8] = [0x00, 0xf4, 0x7c]
let data = Data(fromArray: someBytes)
print(data as NSData)

let bytes = data.toArray(type: UInt8.self)
print(bytes)

1

在Swift 5中的答案很简单,但不在这里找到。遇到了这个问题并找到了答案:

var bytes = [Int8](repeating: 0, count: 32)
let data = Data(bytes: bytes, count: bytes.count)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接