如何在 Swift 中将数据转换为 Doubles、Ints 和 Strings 等类型? [英] How can I convert data into types like Doubles, Ints and Strings in Swift?
问题描述
我正在 iOS Swift 中为 shapefile(一种 GIS 格式,与此问题不是特别相关)构建自定义文件打开器.这些文件有一个 100 字节长的头.我能够将其读入 4 字节数组,其中存储我想要的信息.我可以将这些数组转换为 Swift 类型 Data
和 NSData
,并有一些其他选项来转换它们(如 Base64EncodedString
).但是我无法将这些原始数组或数据或任何格式转换为有用的属性,例如 Double
、Int
和 String
.
I'm working on building a custom file opener in iOS Swift for shapefiles (a GIS format, not particularly relevant to this question). These files have a header which is 100 bytes long. I'm able to read this into 4-byte arrays, which store information I want. I can convert these arrays into the Swift types Data
and NSData
, and have a few other options for transforming them (like Base64EncodedString
). But I'm having trouble converting these raw arrays or the Data or any of the formats into useful attributes like Double
, Int
, and String
.
import Foundation
struct ShapeReader {
var shapeFile = FileHandle(forReadingAtPath: "/Users/christopherjlowrie/Documents/Shapes/SF_Neighborhoods/Planning_Zones.shp")
var fileHeader: String{
let header = shapeFile?.readData(ofLength: 100)
let headerStream = InputStream(data: header!)
headerStream.open()
var buffer = [UInt8](repeating: 0, count: 4)
while (headerStream.hasBytesAvailable){
headerStream.read(&buffer, maxLength: buffer.count)
print(buffer)
let x = Data(buffer)
print(x)
}
return "A"
}
}
目前只返回 A 因为出于测试原因我让它返回一个字符串
如何在 Swift 中打开文件,并将它们的原始字节读入类型(Double
、Ints
、Strings
)?
How can I open files, and read their raw bytes into types (Doubles
, Ints
, Strings
) in Swift?
推荐答案
Xcode 11 • Swift 5.1 或更高版本
从String
或任何Numeric
类型转换为Data
:
extension StringProtocol {
var data: Data { .init(utf8) }
}
<小时>
extension Numeric {
var data: Data {
var source = self
// This will return 1 byte for 8-bit, 2 bytes for 16-bit, 4 bytes for 32-bit and 8 bytes for 64-bit binary integers. For floating point types it will return 4 bytes for single-precision, 8 bytes for double-precision and 16 bytes for extended precision.
return .init(bytes: &source, count: MemoryLayout<Self>.size)
}
}
<小时>
从Data
(字节)转换回String
extension DataProtocol {
var string: String? { String(bytes: self, encoding: .utf8) }
}
<小时>
从 Data
转换回通用的 Numeric
值
extension Numeric {
init<D: DataProtocol>(_ data: D) {
var value: Self = .zero
let size = withUnsafeMutableBytes(of: &value, { data.copyBytes(to: $0)} )
assert(size == MemoryLayout.size(ofValue: value))
self = value
}
}
<小时>
extension DataProtocol {
func value<N: Numeric>() -> N { .init(self) }
}
<小时>
let value = 12.34 // implicit Double 12.34
let data = value.data // double data - 8 bytes
let double = Double(data) // implicit Double 12.34
let double1: Double = .init(data) // explicit Double 12.34
let double2: Double = data.value() // explicit Double 12.34
let double3 = data.value() as Double // casting to Double 12.34
<小时>
现在我们可以轻松地为每个 Numeric
类型添加一个属性:
extension DataProtocol {
var integer: Int { value() }
var int32: Int32 { value() }
var float: Float { value() }
var cgFloat: CGFloat { value() }
var float80: Float80 { value() }
var double: Double { value() }
var decimal: Decimal { value() }
}
<小时>
游乐场测试
Playground testing
let intData = 1_234_567_890_123_456_789.data // 8 bytes (64 bit Integer)
let dataToInt: Int = intData.integer // 1234567890123456789
let intMinData = Int.min.data // 8 bytes (64 bit Integer)
let backToIntMin = intMinData.integer // -9223372036854775808
let intMaxData = Int.max.data // 8 bytes (64 bit Integer)
let backToIntMax = intMaxData.integer // 9223372036854775807
<小时>
let myInt32Data = Int32(1_234_567_890).data // 4 bytes (32 bit Integer)
let backToInt32 = myInt32Data.int32 // 1234567890
let int32MinData = Int32.min.data // 4 bytes (32 bit Integer)
let backToInt32Min = int32MinData.int32 // -2147483648
let int32MaxData = Int32.max.data // 4 bytes (32 bit Integer)
let backToInt32Max = int32MaxData.int32 // 2147483647
<小时>
let myFloatData = Float.pi.data // 4 bytes (32 bit single=precison FloatingPoint)
let backToFloat = myFloatData.float // 3.141593
backToFloat == .pi // true
let myCGFloatData = CGFloat.pi.data // 4 bytes (32 bit single=precison FloatingPoint)
let backToCGFloat = myCGFloatData.cgFloat // 3.141593
backToCGFloat == .pi // true
let myDoubleData = Double.pi.data // 8 bytes (64 bit double-precision FloatingPoint)
let backToDouble = myDoubleData.double // 3.141592653589793
backToDouble == .pi // true
let myFloat80Data = Float80.pi.data // 16 bytes (128 bit extended-precision FloatingPoint)
let backToFloat80 = myFloat80Data.float80 // 3.141592653589793116
backToFloat80 == .pi // true
let decimalData = Decimal.pi.data // 20 bytes Decimal type
let backToDecimal = decimalData.decimal // 3.14159265358979323846264338327950288419
backToDecimal == .pi // true
<小时>
let stringBytes = "Hello World !!!".data.prefix(4) // 4 bytes
let backToString = stringBytes.string // "Hell"
这篇关于如何在 Swift 中将数据转换为 Doubles、Ints 和 Strings 等类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!