Swift 2.1 [UInt8] --utf8 - >字符串?

时间:2015-12-04 01:44:25

标签: swift utf-8 swift2.1

我知道Stack Overflow和其他地方都存在这样的问题。但它似乎也进化了很多。

给定一个UInt8列表(基本上是一个快速的字节数组),将它转换为快速String的最简单/惯用的方法是什么?

我对不使用NSData / NSString的方法特别感兴趣,因为如果Santa将Swift带到Linux世界,那么毫无疑问它将没有NS库,而且我会这样做。想知道如何在Swift中做到这一点。

3 个答案:

答案 0 :(得分:5)

Xcode 8•Swift 3

extension Collection where Iterator.Element == UInt8 {
    var bytes: [UInt8] { return Array(self) }
    var data: Data { return Data(self) }
    var string: String? { return String(data: data, encoding: .utf8) }
}

extension String {
    var data: Data { return Data(utf8) }
}

用法:

let sentence = "Hello World"

let utf8View = sentence.utf8
let bytes = utf8View.bytes     // [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]

let data1 = sentence.data
print(data1 as NSData)         // <48656c6c 6f20576f 726c64>

let data2 = utf8View.data
let data3 = bytes.data
let string1 = utf8View.string  // "Hello World"
let string2 = bytes.string     // "Hello World"
let string3 = data1.string     // "Hello World"

答案 1 :(得分:2)

let buffUInt8: Array<UInt8> = [97, 98, 115, 100, 114, 102, 103, 104, 0]

// you need Int8 array
let buffInt8 = buffUInt8.map{ Int8(bitPattern: $0)}
let str = String.fromCString(buffInt8) // "absdrfgh"

或者你可以使用

String.fromCStringRepairingIllFormedUTF8(cs: UnsafePointer<CChar>) -> (String?, hadError: Bool)

答案 2 :(得分:1)

我实际上最终需要为UInt8的流做这个,并且好奇utf8解码是多么困难。它绝对不是一个班轮,而是通过以下直接实施:

import UIKit

let bytes:[UInt8] = [0xE2, 0x82, 0xEC, 0x00]

var g = bytes.generate()

extension String {
    init(var utf8stream:IndexingGenerator<[UInt8]>) {
        var result = ""
        var codepoint:UInt32 = 0
        while let byte = utf8stream.next() where byte != 0x00 {
            codepoint = UInt32(byte)
            var extraBytes = 0
            if byte & 0b11100000 == 0b11000000 {
                extraBytes = 1
                codepoint &= 0b00011111
            }
            else if byte & 0b11110000 == 0b11100000 {
                extraBytes = 2
                codepoint &= 0b00001111
            }
            else if byte & 0b11111000 == 0b11110000 {
                extraBytes = 3
                codepoint &= 0b00000111
            }
            else if byte & 0b11111100 == 0b11111000 {
                extraBytes = 4
                codepoint &= 0b00000011
            }
            else if byte & 0b11111110 == 0b11111100 {
                extraBytes = 5
                codepoint &= 0b00000001
            }
            for _ in 0..<extraBytes {
                if let additionalByte = utf8stream.next() {
                    codepoint <<= 6
                    codepoint |= UInt32(additionalByte & 0b00111111)
                }
            }
            result.append(UnicodeScalar(codepoint))
        }
        self = result
    }
}

String(utf8stream: g)