当前位置:  开发笔记 > 编程语言 > 正文

将流式传输(utf8)数据转换为字符串的安全方法是什么?

如何解决《将流式传输(utf8)数据转换为字符串的安全方法是什么?》经验,为你挑选了1个好方法。

假设我是用objc/swift编写的服务器.客户端正在向我发送大量数据,这实际上是一个很大的utf8编码字符串.作为服务器,我有我的NSInputStream触发事件,说它有数据要读取.我抓住数据并用它构建一个字符串.

但是,如果下一个数据块落在utf8数据中的不幸位置怎么办?喜欢组成的角色.如果你试图将一块不合规的utf8附加到它上面,似乎会弄乱字符串.

有什么方法可以解决这个问题?我当时认为我可以将数据保存为NSData,但是我无论如何都不知道数据何时被接收(想想数据长度在标题中的HTTP).

谢谢你的任何想法.



1> Rob Napier..:

你可能想在这里使用的工具是UTF8.它将为您处理所有州的问题.请参见如何将解密的UInt8转换为String?一个简单的例子,你可能会适应.

从UTF-8数据构建字符串的主要问题不是组成字符,而是多字节字符."LATIN SMALL LETTER A"+"COMBINING GRAVE ACCENT"即使分别解码每个字符也能正常工作.什么不起作用是收集你的第一个字节,解码它,然后附加解码的第二个字节.不过,该UTF8类型将为您处理此问题.您需要做的就是将您NSInputStream与您联系起来GeneratorType.

这是我正在谈论的基本(不完全生产就绪)的例子.首先,我们需要一种将转换NSInputStream为生成器的方法.这可能是最难的部分:

final class StreamGenerator {
    static let bufferSize = 1024
    let stream: NSInputStream
    var buffer = [UInt8](count: StreamGenerator.bufferSize, repeatedValue: 0)
    var buffGen = IndexingGenerator>([])

    init(stream: NSInputStream) {
        self.stream = stream
        stream.open()
    }
}

extension StreamGenerator: GeneratorType {
    func next() -> UInt8? {
        // Check the stream status
        switch stream.streamStatus {
        case .NotOpen:
            assertionFailure("Cannot read unopened stream")
            return nil
        case .Writing:
            preconditionFailure("Impossible status")
        case .AtEnd, .Closed, .Error:
            return nil // FIXME: May want a closure to post errors
        case .Opening, .Open, .Reading:
            break
        }

        // First see if we can feed from our buffer
        if let result = buffGen.next() {
            return result
        }

        // Our buffer is empty. Block until there is at least one byte available
        let count = stream.read(&buffer, maxLength: buffer.capacity)

        if count <= 0 { // FIXME: Probably want a closure or something to handle error cases
            stream.close()
            return nil
        }

        buffGen = buffer.prefix(count).generate()
        return buffGen.next()
    }
}

调用next()可以在这里阻塞,所以它不应该在主队列上调用,但除此之外,它是一个标准的发送器,它会吐出字节.(这也是可能有很多我不会处理的小角落的部分,所以你想仔细考虑这个.但是,它并不复杂.)

有了它,创建一个UTF-8解码生成器几乎是微不足道的:

final class UnicodeScalarGenerator {
    var byteGenerator: ByteGenerator
    var utf8 = UTF8()
    init(byteGenerator: ByteGenerator) {
        self.byteGenerator = byteGenerator
    }
}

extension UnicodeScalarGenerator: GeneratorType {
    func next() -> UnicodeScalar? {
        switch utf8.decode(&byteGenerator) {
        case .Result(let scalar): return scalar
        case .EmptyInput: return nil
        case .Error: return nil // FIXME: Probably want a closure or something to handle error cases
        }
    }
}

您当然可以将其简单地转换为CharacterGenerator(使用Character(_:UnicodeScalar)).

最后一个问题是如果你想要组合所有组合标记,那么"LATIN SMALL LETTER A"后跟"COMBINING GRAVE ACCENT"将始终一起返回(而不是它们是两个字符).这实际上比听起来有点棘手.首先,您需要生成字符串,而不是字符.然后你需要一个很好的方法来了解所有组合字符是什么.这当然是可以知道的,但我在获得一个简单的算法时遇到了一些麻烦.Cocoa中没有"combineMarkCharacterSet".我还在考虑它.获得"大多数工作"的东西很容易,但我不确定如何构建它以便它对所有Unicode都是正确的.

这是一个试用它的小样本程序:

    let textPath = NSBundle.mainBundle().pathForResource("text.txt", ofType: nil)!
    let inputStream = NSInputStream(fileAtPath: textPath)!
    inputStream.open()

    dispatch_async(dispatch_get_global_queue(0, 0)) {
        let streamGen = StreamGenerator(stream: inputStream)
        let unicodeGen = UnicodeScalarGenerator(byteGenerator: streamGen)
        var string = ""
        for c in GeneratorSequence(unicodeGen) {
            print(c)
            string += String(c)
        }
        print(string)
    }

还有一些文字要读:

Here is some normalish álfa?? text
And some Zalgo i??????n???v????????o?????ke???????? composed stuff
And one more line with no newline

(第二行是一些Zalgo编码文本,非常适合测试.)

我没有在真正的阻塞情况下对此进行任何测试,例如从网络读取,但它应该根据工作方式NSInputStream工作(即它应该阻塞,直到至少有一个字节要读取,但是然后应该只填充缓冲区用任何可用的东西).

我已经完成了所有这些匹配,GeneratorType以便它可以轻松地插入其他内容,但如果您不使用GeneratorType而错误处理可能会更好,而是创建自己的协议next() throws -> Self.Element.抛出可以更容易地将错误传播到堆栈中,但会使插入for...in循环变得更加困难.

推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有