在Swift中写作时,我有一个特定的需求,可能是类型双关的候选者。我正在从磁盘映像中读取文件,这些文件位于512字节的连续扇区中。文件从磁盘上以Data
结构的形式出现,它可以很容易地转换为字节数组和/或512字节的DataSlices
,而不需要复制。
到目前为止,一切都很好!文件可以快速表示为包含512个UInt8
单元的数组的集合。但是,一些磁盘扇区(通常包含元数据(最好作为256个UInt16
项处理。理想情况下,我希望能够以任何一种方式引用内存中的扇区,而不需要任何复制。
现在,我正在采取一种简单的方法,将一个扇区(需要两个副本(复制到以下内容中:
struct Sector {
let bytes: [UInt8]
let words: [UInt16]
. . .
init() {
self.bytes = Array(repeating: 0, count: 512)
self.words = Array(repeating: 0, count: 256)
. . .
然后参考CCD_ 5或CCD_。幸运的是,[UInt16]
扇区比它们的字节等价物要少得多,所以这并不太糟糕;任何给定的扇区都是其中之一,我不必担心更改bytes
不会更改words
(尽管这是一个等待发生的事故(。
我读到的所有内容都谴责对[UInt8]
和[UInt16]
数组的攻击,Swift的"不安全"内存函数有些吓人。我正试图想出一种方法,使上面结构中的.words
与.bytes
占用相同的内存,并希望提供一些建议。
我还在做这件事。。如果我发现有价值的东西,我会分享。
您正在寻找中描述的技术https://stackoverflow.com/a/38024025/341994.将数据保存在data中,并根据需要将其作为UInt8或UInt16的数组进行访问。(实际上,Data是UInt8的数组,所以当你想把它看作UInt16的数组时,你只需要做任何特别的事情。(示例:
extension Data {
init<T>(fromArray values: [T]) {
self = values.withUnsafeBytes { Data($0) }
}
func toArray<T>(type: T.Type) -> [T] where T: ExpressibleByIntegerLiteral {
var array = Array<T>(repeating: 0, count: self.count/MemoryLayout<T>.stride)
_ = array.withUnsafeMutableBytes { copyBytes(to: $0) }
return array
}
}
let eights : [UInt8] = [1,2,3,4]
let data = Data(fromArray:eights)
let sixteens = data.toArray(type: UInt16.self)
print(sixteens) // 513, 1027
这是正确的答案,假设顺序正确;
0b00000001
为10b00000010
为2
因此,假设低字节高字节:
0b0000001000000001
为513
将其移动到类型中!
struct Sector<Datum: FixedWidthInteger> {
let data: [Datum]
init() {
data = .init(repeating: 0, count: 0x1000 / Datum.bitWidth)
}
}
typealias Byte = UInt8
typealias Word = UInt16
Sector<Byte>().data.count // 512
Sector<Word>().data.count // 256