如何在 Swift 中将数据转换为 Doubles、Ints 和 Strings 等类型? [英] How can I convert data into types like Doubles, Ints and Strings in Swift?

查看:48
本文介绍了如何在 Swift 中将数据转换为 Doubles、Ints 和 Strings 等类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 iOS Swift 中为 shapefile(一种 GIS 格式,与此问题不是特别相关)构建自定义文件打开器.这些文件有一个 100 字节长的头.我能够将其读入 4 字节数组,其中存储我想要的信息.我可以将这些数组转换为 Swift 类型 DataNSData,并有一些其他选项来转换它们(如 Base64EncodedString).但是我无法将这些原始数组或数据或任何格式转换为有用的属性,例如 DoubleIntString.

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 中打开文件,并将它们的原始字节读入类型(DoubleIntsStrings)?

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆