如何在 Swift 中获取任意数组的字节大小?
Posted
技术标签:
【中文标题】如何在 Swift 中获取任意数组的字节大小?【英文标题】:How to get bytes size for arbitrary array in Swift? 【发布时间】:2015-11-19 10:12:20 【问题描述】:我想使用let rawDataFromArray = NSData(bytes: myArray, length: ???)
,但不知道如何获取数组的字节长度。以下是我的数组的一些示例:
let arr1 = [1, 2, 3]
let arr2 = [1.0, 23556789000.0]
let arr3 = ["hello", "ok", "????"]
func arrayLength(myArray: Array) -> Int
var bytes = 0
for object in myArray
// not sure what to do here
return bytes
我不确定遍历数组的每个元素(如果字符串遍历每个字符,因为表情符号可能有更多字节表示它们)是否是正确的方法。
如何获取数组的字节大小?
谁能告诉我正确的做法?
或者也许只是在 Swift 中将 Array
转换为 NSData
不是一个好习惯?
我也见过Converting Swift Array to NSData for persistent storage 和Converting array of bytes to NSData 和Custom Array to NSData,但不知道如何获取这种任意数组的字节大小。
【问题讨论】:
请参阅***.com/questions/25714086/… 以获取可用于整数或浮点数数组的示例。但是您不能简单地将 strings 数组视为 NSData,因为String
结构(具有固定大小)包含指向实际字符存储的不透明指针。
感谢@MartinR。因此,将字符串数组转换为 NSData 看起来是个坏主意。你能解释一下什么是不透明指针吗?
struct String
具有不属于“可见”API 的成员(但您可以在调试器中看到它们)。其中一些是指向用于字符串的实际存储的指针。 (例如,相同的字符串可以共享>存储。) – 关键是struct String
不是自包含的。如果将其打包到 NSData 中,将其转移到其他地方并解包,它将包含无效指针。 – 当然,您可以从字符串数组创建 NSData,但必须单独附加每个字符串(例如,作为 NUL 终止的 UTF-8 字符串)。
或者,使用 NSKeyedArchiver (如在您引用的线程中)。这取决于您要如何处理数据。
【参考方案1】:
似乎有一个误解:对于每个类型T
,所有实例
T
的大小相同,可以计算为 sizeof(T)
。
在数组的情况下,数组元素之间可以有一个padding,
因此arr1
所需的总大小为
arr1.count * strideof(Int)
(比较例如Swift: How to use sizeof? 以了解sizeof()
和strideof()
之间的细微差别)。
因此,从数组创建NSData
的通用函数将是
extension Array
func asData() -> NSData
return self.withUnsafeBufferPointer(
NSData(bytes: $0.baseAddress, length: count * strideof(Element))
)
使用withUnsafeBufferPointer()
保证数组使用
其元素的连续存储。
对于像Int
和Float
这样的“简单”类型,这给出了
预期结果:
let arr1 = [1, 2, 3]
print(arr1.asData())
// <01000000 00000000 02000000 00000000 03000000 00000000>
let arr2 = [1.0, 23556789000.0]
print(arr2.asData())
// <00000000 0000f03f 0000204c 60f01542>
但是,对于字符串数组是没有用的:
let arr3 = ["hello", "ok", "?"]
print(arr3.asData())
// <945b2900 01000000 05000000 00000000 00000000 00000000 9a5b2900 01000000 02000000 00000000 00000000 00000000 068d2900 01000000 02000000 00000080 00000000 00000000>
因为struct String
包含(隐藏/未记录的)指向实际的指针
字符存储。
一种可能性是将每个字符串附加为以 NUL 结尾的 UTF-8 字符串:
let data3 = NSMutableData()
arr3.forEach string in
string.withCString
data3.appendBytes($0, length: Int(strlen($0)) + 1)
print(data3)
// <68656c6c 6f006f6b 00f09f91 8d00>
或者,在您引用的线程中使用NSKeyedArchiver
。
【讨论】:
strideof(T)
是 MemoryLayout<T>.stride
(截至... Swift 3?)以上是关于如何在 Swift 中获取任意数组的字节大小?的主要内容,如果未能解决你的问题,请参考以下文章