Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 4 Int32至[UInt8]_Swift_Swift4 - Fatal编程技术网

Swift 4 Int32至[UInt8]

Swift 4 Int32至[UInt8],swift,swift4,Swift,Swift4,我试图将整数中的字节转换成[UInt8],通过有线协议发送。虽然我发现答案适用于Swift 2/3,但没有一个解决方案适用于Swift 4 以下代码段用于对较小消息大小的消息进行编码(仅使用网络字节顺序Int32 size前缀的原始字符串数据): 我也尝试过直接使用原始指针,但也无法在这条路上为Swift 4找到任何工作 总体任务是对由整数和字符串组成的消息进行编码和帧处理。编码将所有内容转换为字符串,并在每个字符串的末尾添加空值。帧只是在消息前面加上网络字节顺序Int32大小。我不能改变协议,

我试图将整数中的字节转换成[UInt8],通过有线协议发送。虽然我发现答案适用于Swift 2/3,但没有一个解决方案适用于Swift 4

以下代码段用于对较小消息大小的消息进行编码(仅使用网络字节顺序Int32 size前缀的原始字符串数据):

我也尝试过直接使用原始指针,但也无法在这条路上为Swift 4找到任何工作

总体任务是对由整数和字符串组成的消息进行编码和帧处理。编码将所有内容转换为字符串,并在每个字符串的末尾添加空值。帧只是在消息前面加上网络字节顺序Int32大小。我不能改变协议,但我愿意考虑其他方法来实现这一目标。 干杯

[编辑]使用@MartinR的代码(根据@Hamish的建议)更新代码。同时在总体任务上也取得了一些进展

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)
    }
}