首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift UTF16子串

Swift UTF16子串
EN

Stack Overflow用户
提问于 2015-12-07 19:41:16
回答 2查看 1.4K关注 0票数 0

我正在接收来自服务器的字符串,格式如下:

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中完成它(或者它是否可以完成)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-07 21:04:12

下面是我对从字符串中解析消息的看法。我不得不改变你的长度来处理绳子。

代码语言:javascript
复制
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)

我最后得到的输出是:

代码语言:javascript
复制
["...message...", "...message2..."]
票数 3
EN

Stack Overflow用户

发布于 2015-12-07 20:42:16

Foundation框架将String扩展为可从数据初始化:

代码语言:javascript
复制
import Foundation

let string = String(data: data, encoding: NSUTF16StringEncoding)

除非您自己实现解码,否则摆脱Foundation是不可能的。请注意,随着Swift的开源,Foundation将在没有Objective依赖这里的情况下重新实现。

编辑:谢谢,马丁·R,你提供的链接确实是用纯Swift :D提供的

编辑:

有一个utf16属性的String,其count属性是UTF16中的长度。下面是一个简单的解析器,用于您的目的,效率不是很好,但它完成了任务:

代码语言:javascript
复制
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⚽️"]

实际上我试过让它更有效率,但是斯威夫特的绳子力学把它推到了.我要求任何人为此创建一个漂亮、高效、安全的解析器。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34141793

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档