【问题标题】:Convert each Byte of NSData to equivalent Int Value将 NSData 的每个字节转换为等效的 Int 值
【发布时间】:2015-10-19 23:12:25
【问题描述】:

我有一个 NSData 对象,它分配有代表 0-255 无符号整数的字节。将这些字节转换为整数,或者如果更简单的话,转换为字符串/NSString 的最简单方法是什么?

例如,如果我的 NSData 对象中有字节 0x00、0x02 和 0x0A,那么我想要一个整数数组 {0,2,10} 或字符串/NSString“0210”。

似乎有很多方法可以将 NSData 转换为 ASCII NSStrings、UInt8 数组等,但我一生都无法弄清楚如何在 Swift 中进行这种简单的转换。

编辑:我想要的示例代码:

var data:NSData
/*allocate NSData*/
var unsignedInts = [Int]()
/*Allocate each byte of data to an individual index of unsignedInts */
print(unsignedInts)
//should see {0, 1, 10} if bytes are 0x00, 0x01, and 0x0A

【问题讨论】:

标签: swift


【解决方案1】:

有必要创建一个新的 Int 数组,因为 Int 每个条目需要更多字节。

var nsData: NSData = NSData(bytes: [0x00, 0x02, 0x0A] as [UInt8], length: 3)
let buffer = UnsafeBufferPointer<UInt8>(start:UnsafePointer<UInt8>(nsData.bytes), count:nsData.length)
print("nsData: \(nsData)")

var intData = [Int]()
intData.reserveCapacity(nsData.length)

var stringData = String()

for i in 0..<nsData.length {
    intData.append(Int(buffer[i]))
    stringData += String(buffer[i])
}

print("intData: \(intData)")
print("stringData: \(stringData)")

nsData:
intData: [0, 2, 10]
字符串数据:0210

【讨论】:

  • 感谢您抽出宝贵时间@zaph,非常感谢。
  • 这不是很有效,因为intArraystringData 必须分配很多新内存。你应该使用reserveCapacity 来避免这种情况
  • @zaph 更好,但reserveCapacity 不占用字节数,而是占用元素数(不需要sizeofs)。此外,字符串实际上需要大约 2-3 倍的元素,因为 UInt8 的字符串范围可以从“0”(1 个字符)到“256”(3 个字符),应该是 3 倍。如果你想要数学:1个字符的10/256概率,2个字符的90/256概率,3个字符的156/256概率给出大约2.57的因子(假设随机分布),这将给出stringData.reserveCapacity(Int(Double(nsData.length) * 2.57)))。当然这只是一个细节,append反正也不错
  • @Kametrixom 感谢您提供的信息,是的,我完全错过了考虑字节字符串表示所需的大小。我已经删除了字符串的reserveCapacity,因为它提供了最小的改进(
【解决方案2】:

我可以推荐一个这样的方法:

import Foundation

extension NSData {
    var byteBuffer : UnsafeMutableBufferPointer<UInt8> {
        return UnsafeMutableBufferPointer(start: UnsafeMutablePointer(bytes), count: length)
    }

    var array : [UInt8] {
        return Array(byteBuffer)
    }

    var intArray : [Int] {
        return byteBuffer.map(Int.init)
    }

    var byteString : String {
        return byteBuffer.lazy.map(String.init).joinWithSeparator("")
    }
}

用法:

let data1 = NSData(bytes: [0x48, 0xa1, 0x95, 0xe, 0x1c, 0x38, 0x82] as [UInt8], length: 7)       // <48a1950e 1c3882>

print(data1.array)       // "[72, 161, 149, 14, 28, 56, 130]"
print(data1.intArray)    // "[72, 161, 149, 14, 28, 56, 130]"
print(data1.byteString)  // "72161149142856130"

let data2 = NSData(bytes: [0x00, 0x02, 0x0A] as [UInt8], length: 3)

print(data2.array)       // "[0, 2, 10]"
print(data2.intArray)    // "[0, 2, 10]"
print(data2.byteString)  // "0210"

像这样非常简单、Swift-y 和高效。

请注意,在某些情况下,您实际上并不需要这样的数组,因为您可以以相同的方式访问数据的所有值,而无需分配新数组(推荐):

data1.byteBuffer[4]      // 28
data1.byteBuffer.count   // 7
data1.byteBuffer(14)     // 3

编辑:我添加了一个返回 Int 数组的属性,虽然我看不出你需要它的原因

【讨论】:

  • @zaph 我编辑了我的答案,尽管这并不是对 imho 投反对票的真正理由
  • @zaph btw 看看当您将鼠标悬停在否决按钮上时它所说的内容:“这个答案没有用”-> 否决票不适用于没有 100% 回答原始答案的答案问题
  • 看来您确实对 Swift 有很好的掌握,并且答案提供了正确的答案,但我不同意该解决方案。 IMO 的解决方案很糟糕。
  • @zaph 你为什么不同意?我只是选择了更实用的方式(本着 Swift 的精神),而你选择了命令式的方式
  • 如果你想聊聊为什么让我知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 2011-08-30
相关资源
最近更新 更多