我正在使用iOS Swift在Shapefile文件(一种GIS格式,与这个问题没有特别关系)中构建自定义文件打开器。这些文件的头长度为100个字节。我能够将其读入4字节的数组中,该数组存储了我想要的信息。我可以将这些数组转换为Swift类型Data和NSData,并具有其他一些转换它们的选项(例如Base64EncodedString)。但我无法将这些原料阵列或数据或任何的格式转换成有用的属性等Double,Int和String。
Data
NSData
Base64EncodedString
Double
Int
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,因为出于测试原因,我让它返回一个字符串
我怎么能打开文件,并阅读他们的原始字节分为不同的类型(Doubles,Ints,Strings)的斯威夫特?
Doubles
Ints
Strings
Xcode 11•Swift 5.1或更高版本
转换:String或从任何Numeric类型转换为Data:
Numeric
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() } }
游乐场测试
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"