如何在 Swift 中使用 htonl 设置整数字节顺序?
Posted
技术标签:
【中文标题】如何在 Swift 中使用 htonl 设置整数字节顺序?【英文标题】:How do I set integer endianness using htonl in Swift? 【发布时间】:2014-06-24 19:21:46 【问题描述】:我正在尝试在 Swift 中使用 htonl()
设置整数字节顺序,但编译器没有找到 htonl()
方法。
我一直以此为参考:Append NSInteger to NSMutableData
这是我的代码:
import Foundation
import CFNetwork
import CoreFoundation
var data = NSMutableData()
var number : UInt32 = 12
var convertedNumber : UInt32 = htonl(number)
data.appendBytes(&convertedNumber, length: 4)
我刚刚在操场上运行它。错误是:
Use of unresolved identifier 'htonl'
【问题讨论】:
【参考方案1】:从 Xcode 6 Beta 3 开始,所有整数类型都有一个 bigEndian
方法
返回整数的大端表示并更改
必要时字节顺序。示例:
var data = NSMutableData()
var number : UInt32 = 0x12345678
var convertedNumber = number.bigEndian
data.appendBytes(&convertedNumber, length: 4)
print(data)
// Output: <12345678>
Swift 3 更新:
let data = NSMutableData()
let number: UInt32 = 0x12345678
var convertedNumber = number.bigEndian
data.append(&convertedNumber, length: 4)
或者,使用新的Data
值类型:
var data = Data()
let number: UInt32 = 0x12345678
var convertedNumber = number.bigEndian
withUnsafePointer(to: &convertedNumber)
data.append(UnsafeRawPointer($0).assumingMemoryBound(to: UInt8.self), count: 4)
【讨论】:
如果您正在寻找相反的方向(网络到主机),您可以使用UInt32(bigEndian: number)
,以及类似的inits
用于其他整数类型。【参考方案2】:
更新:Martin R 的答案是当前 Swift 版本的正确答案:https://***.com/a/24653879/195691
--
您应该使用CFSwapInt32HostToBig()
CoreFoundation 方法,因为htonl
很可能实现为不能在swift 中运行的C 宏。
但是,目前看来这在 Swift 游乐场中不起作用。尽管 CoreFoundation 文档现在在 Swift 中包含用于字节交换方法的方法签名,但我收到了错误 Playground execution failed: error: error: Couldn't lookup symbols: __OSSwapInt32
。
有趣的是,<arpa/inet.h>
的至少一部分似乎已移植到 swift,因为 inet_ntoa()
和 inet_addr()
等方法可用于 Swift,但 htonl
系列不可用。
【讨论】:
太棒了,谢谢!看起来这会奏效。我最终在桥接头/native-c 中实现了 htonl(),但我会切换到这个。 对。 htonl/htons 等是一个宏,因此不会导入到 Swift 中(像 ioctl/fcntl 这样的可变参数 C 函数是另一个常见的缺失)。如果你知道字节序很容易重新实现:func ntohs(value: CUnsignedShort) -> CUnsignedShort // hm, htons 在 OSX 中不是 func 并且宏没有映射 return (value > 8); let htons = ntohs // 同样的事情,交换字节 :-) 其实CFSwapInt32HostToBig
和朋友们现在可以在 Xcode 6.1.1 自带的 Swift 中使用 :)
@MartinR 这可能是真的,但UInt32.bigEndian
、UInt32.littleEndian
和UInt32.byteSwapped
似乎比使用CFSwapInt32HostToBig
更好
PSA 5.bigEndian.littleEndian
不等于 5!然而,CFSwapInt16BigToHost(CFSwapInt16HostToBig(5))
实际上等于 5!【参考方案3】:
不要像 Alex Pretzlav 建议的那样使用 CFSwapInt32HostToBig(),而是应该使用
CFSwapInt32()
而不是
ntonl() and ntohl()
和
CFSwapInt16()
而不是
ntons() and ntohs()
你的代码应该是这样的
import Foundation
import CFNetwork
import CoreFoundation
var data = NSMutableData()
var number : UInt32 = 12
var convertedNumber : UInt32 = CFSwapInt32(number)
data.appendBytes(&convertedNumber, length: 4)
还有
CFSwapInt64()
用于 8 字节整数交换。
编辑 1
当然,您应该只在具有小端整数的处理器上使用这些函数,因为我提供的函数无论如何都会执行字节交换。
【讨论】:
我不明白你的回答。你说不要使用CFSwapInt32HostToBig
,建议你改用CFSwapInt32
,然后是“你应该只在具有小端整数的处理器上使用这些函数”……CFSwapInt32HostToBig
的全部意义在于它可以交换,或者不会,具体取决于平台。以上是关于如何在 Swift 中使用 htonl 设置整数字节顺序?的主要内容,如果未能解决你的问题,请参考以下文章
使用 JSONDecoder Swift 解码具有整数值的字符串键 [关闭]
使用 Swift,从 plist 加载数据时,如何区分布尔值和整数值?
如何限制 UITextField 在 Swift 中只接受数字?