Swift 4 Int32至[UInt8]
我试图将整数中的字节转换成[UInt8],通过有线协议发送。虽然我发现答案适用于Swift 2/3,但没有一个解决方案适用于Swift 4 以下代码段用于对较小消息大小的消息进行编码(仅使用网络字节顺序Int32 size前缀的原始字符串数据): 我也尝试过直接使用原始指针,但也无法在这条路上为Swift 4找到任何工作 总体任务是对由整数和字符串组成的消息进行编码和帧处理。编码将所有内容转换为字符串,并在每个字符串的末尾添加空值。帧只是在消息前面加上网络字节顺序Int32大小。我不能改变协议,但我愿意考虑其他方法来实现这一目标。 干杯 [编辑]使用@MartinR的代码(根据@Hamish的建议)更新代码。同时在总体任务上也取得了一些进展Swift 4 Int32至[UInt8],swift,swift4,Swift,Swift4,我试图将整数中的字节转换成[UInt8],通过有线协议发送。虽然我发现答案适用于Swift 2/3,但没有一个解决方案适用于Swift 4 以下代码段用于对较小消息大小的消息进行编码(仅使用网络字节顺序Int32 size前缀的原始字符串数据): 我也尝试过直接使用原始指针,但也无法在这条路上为Swift 4找到任何工作 总体任务是对由整数和字符串组成的消息进行编码和帧处理。编码将所有内容转换为字符串,并在每个字符串的末尾添加空值。帧只是在消息前面加上网络字节顺序Int32大小。我不能改变协议,
func encodeMessagePart(_ message: String) -> [UInt8] {
var buffer: [UInt8] = Array(message.utf8)
buffer.append(0)
return buffer
}
func encodeMessagePart(_ message: Int) -> [UInt8] {
return encodeMessagePart("\(message)")
}
func frameMessage(_ buffer: [UInt8]) -> [UInt8] {
let bufferSize = buffer.count
var encodedBufferSize = Int32(bufferSize).bigEndian
let encodedBufferSizeData = withUnsafeBytes(of: &encodedBufferSize) { Data($0) }
var frame: [UInt8] = Array()
frame.append(contentsOf: encodedBufferSizeData)
frame.append(contentsOf: buffer)
return frame
}
func sendMessage(_ buffer: [UInt8]) {
let frame = frameMessage(buffer)
outputStream.write(frame, maxLength: frame.count)
}
func sendMessage(_ message: String) {
let encodedPart = encodeMessagePart(message)
sendMessage(encodedPart)
}
// func sendMessage(_ messages: Encodable...) {
// var buffer: [UInt8] = Array()
// for message in messages {
// let b = encodeMessagePart(message)
// buffer.append(contentsOf: b)
// }
// sendMessage(buffer)
// }
您可以使用
let encodedMessageSize = Int32(messageSize).bigEndian
let data = withUnsafeBytes(of: encodedMessageSize) { Data($0) }
(在4.2之前的Swift版本中,您必须编写
var encodedMessageSize = Int32(messageSize).bigEndian
let data = withUnsafeBytes(of: &encodedMessageSize) { Data($0) }
相反。)
然后,可以使用
buffer.append(contentsOf: data)
或者,您可以使用数据
缓冲区而不是数组:
func send(message: String) {
let messageSize = message.utf8.count
let encodedMessageSize = Int32(messageSize).bigEndian
var data = withUnsafeBytes(of: encodedMessageSize) { Data($0) }
data.append(Data(message.utf8))
let amountWritten = data.withUnsafeBytes { [count = data.count] in
outputStream.write($0, maxLength: count)
}
}
最后请注意,write()
方法写入的字节可能少于
提供(例如,在网络连接上),因此您应该始终检查
返回值。请注意,
message.utf8
没有在字符串末尾添加null。遗憾的是,数据(缓冲区:UnsafeBufferPointer(开始:&encodedMessageSize,计数:1))
没有很好地定义,由于&encodedMessageSize
的inout-to-pointer转换生成的指针仅在调用UnsafeBufferPointer.init
期间有效。您可以改为使用withUnsafeBytes(of::)
——例如withUnsafeBytes(of:&encodedMessageSize){Data($0)}
。在Swift 4.2+中,encodedMessageSize
可以是一个常量,并且可以非inout传递:)@Hamish:你是对的(我现在记得不久前我是怎么想的,但又忘了)。似乎我应该利用周末来重写:)希望该语言的未来版本能够防止对Unsafe[…]的参数进行这种临时转换。init
调用(实际上我已经有了一个实验分支,可以做到这一点,但在PR之前还需要进一步完善),在我看来,很容易不小心对它们做了错误的事情(可能会出错!)@MartinR:使用数据与[UInt8]相比有什么利弊?@RandomBits:有一份报告说,数据
比数组
()慢,但这可能只与更大的数量有关。
func send(message: String) {
let messageSize = message.utf8.count
let encodedMessageSize = Int32(messageSize).bigEndian
var data = withUnsafeBytes(of: encodedMessageSize) { Data($0) }
data.append(Data(message.utf8))
let amountWritten = data.withUnsafeBytes { [count = data.count] in
outputStream.write($0, maxLength: count)
}
}