我正在接收来自服务器的字符串,格式如下:
118|...message...215|...message2...
基本上,它是消息长度,后面是管道和消息本身,对于多个消息重复。该消息被编码为UTF16。
我在寻找一种在Swift中解析这个的方法。我知道我可以将其转换为NSString,并在其上使用标准索引/范围,因为UTF16是NSString所使用的,但我想知道如何使用Swift方法来处理这个问题呢?我似乎找不到一种基于String编码从UTF16中提取子字符串的方法。
更新
我并不试图用原始的String数据初始化UTF16 (有很多方法可以做到这一点)。我已经有了字符串,所以我尝试以上述格式获取一个String并对其进行解析。我的问题是服务器给我的消息长度是基于UTF16的。我不能简单地提取长度并在索引上调用String.advance(messageLength),因为给定的长度与Swift所推进的字形簇不匹配。我的问题是我无法从字符串中提取Swift中的消息。我不得不将其转换为NSString,然后在其上使用“普通”NSRange。我的问题是如何提取子字符串,根据对第一个管道的搜索提取一个范围,然后使用解析器在UTF16中提供的长度。
这对于NSString来说是非常简单的。不确定如何在纯Swift中完成它(或者它是否可以完成)。
发布于 2015-12-07 21:04:12
下面是我对从字符串中解析消息的看法。我不得不改变你的长度来处理绳子。
let message = "13|...message...14|...message2..."
let utf16 = message.utf16
var startingIndex = message.utf16.startIndex
var travellingIndex = message.utf16.startIndex
var messages = [String]()
var messageLength: Int
while travellingIndex != message.utf16.endIndex {
// Start walking through each character
if let char = String(utf16[travellingIndex..<travellingIndex.successor()]) {
// When we find the pipe symbol try to parse out the message length
if char == "|" {
if let stringNumber = Int(String(utf16[startingIndex..<travellingIndex])) {
messageLength = stringNumber
// We found the lenght, now skip the pipe character
startingIndex = travellingIndex.successor()
// move the travelingIndex to the end of the message
travellingIndex = travellingIndex.advancedBy(messageLength)
// get the message and put it into an array
if let message = String(utf16[startingIndex...travellingIndex]) {
messages.append(message)
startingIndex = travellingIndex.successor()
}
}
}
}
travellingIndex = travellingIndex.successor()
}
print(messages)我最后得到的输出是:
["...message...", "...message2..."]发布于 2015-12-07 20:42:16
Foundation框架将String扩展为可从数据初始化:
import Foundation
let string = String(data: data, encoding: NSUTF16StringEncoding)除非您自己实现解码,否则摆脱Foundation是不可能的。请注意,随着Swift的开源,Foundation将在没有Objective依赖这里的情况下重新实现。
编辑:谢谢,马丁·R,你提供的链接确实是用纯Swift :D提供的
编辑:
有一个utf16属性的String,其count属性是UTF16中的长度。下面是一个简单的解析器,用于您的目的,效率不是很好,但它完成了任务:
func getMessages(var string: String) -> [String]? {
func getMessage(string: String) -> (message: String, rest: String)? {
guard let
index = string.characters.indexOf("|"),
length = Int(String(string.characters.prefixUpTo(index)))
else { return nil }
let msgRest = String(string.characters.suffixFrom(index.successor()))
return (String(msgRest.utf16.prefix(length)), String(msgRest.utf16.dropFirst(length)))
}
var messages : [String] = []
while let (message, rest) = getMessage(string) {
string = rest
messages.append(message)
}
return messages
}
func stringForMessages(messages: [String]) -> String {
return messages.map{ "\($0.utf16.count)|\($0)" }.joinWithSeparator("")
}
let messages = [
"123",
"",
"",
"6⚽️"
]
let string = stringForMessages(messages)
let received = getMessages(string)
messages // ["123", "", "", "6⚽️"]实际上我试过让它更有效率,但是斯威夫特的绳子力学把它推到了.我要求任何人为此创建一个漂亮、高效、安全的解析器。
https://stackoverflow.com/questions/34141793
复制相似问题