2014-06-28 41 views

回答

1

这是一个可能的解决方案(现在更新的夫特2):

let utf8 : [CChar] = [65, 66, 67, 0] 
if let str = utf8.withUnsafeBufferPointer({ String.fromCString($0.baseAddress) }) { 
    print(str) // Output: ABC 
} else { 
    print("Not a valid UTF-8 string") 
} 

内闭合,$0UnsafeBufferPointer<CChar>指向阵列的连续的存储。由此可以创建Swift String

或者,如果你喜欢的输入作为无符号字节:

let utf8 : [UInt8] = [0xE2, 0x82, 0xAC, 0] 
if let str = utf8.withUnsafeBufferPointer({ String.fromCString(UnsafePointer($0.baseAddress)) }) { 
    print(str) // Output: € 
} else { 
    print("Not a valid UTF-8 string") 
} 
+0

使用Swift语法编写的C代码......并且比C更丑陋(这可能是一件好事,所以人们希望避免它们) –

+1

@BryanChen:我刚才试图提出一个不使用Swift的解决方案基金会和Objective-C类... –

+0

我认为真正的雨燕方法必须使用'Character'和'UTF8'某处 –

1

我会做这样的事情,也可能是没有这样优雅比“指针”工作,但它的工作好,这些是相当多的关于一堆新+=运营商String,如:

@infix func += (inout lhs: String, rhs: (unit1: UInt8)) { 
    lhs += Character(UnicodeScalar(UInt32(rhs.unit1))) 
} 

@infix func += (inout lhs: String, rhs: (unit1: UInt8, unit2: UInt8)) { 
    lhs += Character(UnicodeScalar(UInt32(rhs.unit1) << 8 | UInt32(rhs.unit2))) 
} 

@infix func += (inout lhs: String, rhs: (unit1: UInt8, unit2: UInt8, unit3: UInt8, unit4: UInt8)) { 
    lhs += Character(UnicodeScalar(UInt32(rhs.unit1) << 24 | UInt32(rhs.unit2) << 16 | UInt32(rhs.unit3) << 8 | UInt32(rhs.unit4))) 
} 

注:您可以扩展与overridin支持的运营商名单g+运营商以及定义完全可交换运营商的列表String


,现在你可以到String追加使用Unicode(UTF-8,UTF-16和UTF-32)字符例如像:

var string: String = "signs of the Zodiac: " 
string += (0x0, 0x0, 0x26, 0x4b) 
string += (38) 
string += (0x26, 76) 
+0

只是一句话:你的代码创建从UTF-32输入一个字符串(如果我理解正确的话)和雷来自UTF-8输入。再次读这个问题我不是100%确定这里要求什么。 OP提到两个“UTF-8”和“码点” ... –

+0

@MartinR,你是对的,是公平的,我不知道真正的问题提出,其原因是,就像你刚才说的一样。 .. – holex

+0

请注意,Unicode代码点的UTF-8序列具有1个,2个,3个或4个字节。 –

4

改善马丁的r答案

import AppKit 

let utf8 : CChar[] = [65, 66, 67, 0] 
let str = NSString(bytes: utf8, length: utf8.count, encoding: NSUTF8StringEncoding) 
println(str) // Output: ABC 

import AppKit 

let utf8 : UInt8[] = [0xE2, 0x82, 0xAC, 0] 
let str = NSString(bytes: utf8, length: utf8.count, encoding: NSUTF8StringEncoding) 
println(str) // Output: € 

发生了什么事是Array可以自动转换到CConstVoidPointer可用于与NSSString(bytes: CConstVoidPointer, length len: Int, encoding: Uint)

+3

请注意,您的代码也会将0字节转换为创建的NSString中的NUL字符。 –

12

这是可能的UTF8编码点转换为字符串雨燕习惯用法使用UTF8雨燕类中创建的字符串。虽然从String转换为UTF8更容易!

import Foundation 

public class UTF8Encoding { 
    public static func encode(bytes: Array<UInt8>) -> String { 
    var encodedString = "" 
    var decoder = UTF8() 
    var generator = bytes.generate() 
    var finished: Bool = false 
    do { 
     let decodingResult = decoder.decode(&generator) 
     switch decodingResult { 
     case .Result(let char): 
     encodedString.append(char) 
     case .EmptyInput: 
     finished = true 
     /* ignore errors and unexpected values */ 
     case .Error: 
     finished = true 
     default: 
     finished = true 
     } 
    } while (!finished) 
    return encodedString 
    } 

    public static func decode(str: String) -> Array<UInt8> { 
    var decodedBytes = Array<UInt8>() 
    for b in str.utf8 { 
     decodedBytes.append(b) 
    } 
    return decodedBytes 
    } 
} 

func testUTF8Encoding() { 
    let testString = "A UTF8 String With Special Characters: " 
    let decodedArray = UTF8Encoding.decode(testString) 
    let encodedString = UTF8Encoding.encode(decodedArray) 
    XCTAssert(encodedString == testString, "UTF8Encoding is lossless: \(encodedString) != \(testString)") 
} 

另一替代方案建议:

  • 使用NSString调用Objective-C的桥;

  • 使用UnicodeScalar容易出错,因为它将UnicodeScalars直接转换为字符,忽略复杂的字素集群;和

  • 使用String.fromCString可能是不安全的,因为它使用指针。

+2

感谢您解码UTF8编码!你可以从顶部删除'import Foundation',这就是我想要使用它的全部原因。 – ephemer

+0

谢谢!很有帮助。这是一个链接到沙盒与这对夫妇的更新工作,使解码更容易一点。 http://swiftlang.ng.bluemix.net/#/repl/2dde62756a95d6d1c7bb88068cb35ebfe4b13ffc3ec891856992166caa8a291d – Pat

+0

您使用的词语“编码”和“解码”的是我如何看待字符串和UTF-8的数据之间进行转换相反。 – RenniePet

0

我一直在寻找一个全面的答案在Swift我自己的字符串操作。依靠铸造NSString和其他不安全的指针魔术就是不适合我。这里是一个安全的选择:

首先,我们要扩展UInt8。这是CodeUnit后面的原始类型。

extension UInt8 { 
    var character: Character { 
     return Character(UnicodeScalar(self)) 
    } 
} 

这将使我们能够做这样的事情:

let codeUnits: [UInt8] = [ 
    72, 69, 76, 76, 79 
] 

let characters = codeUnits.map { $0.character } 
let string  = String(characters) 

// string prints "HELLO" 

配备了这个扩展,我们现在正在修改字符串。

let string = "ABCDEFGHIJKLMONP" 

var modifiedCharacters = [Character]() 
for (index, utf8unit) in string.utf8.enumerate() { 

    // Insert a "-" every 4 characters 
    if index > 0 && index % 4 == 0 { 
     let separator: UInt8 = 45 // "-" in ASCII 
     modifiedCharacters.append(separator.character) 
    } 
    modifiedCharacters.append(utf8unit.character) 
} 

let modifiedString = String(modifiedCharacters) 

// modified string == "ABCD-EFGH-IJKL-MONP" 
+0

我是否正确地认为这只适用于ASCII字符串?也就是说,如果字符串中有丹麦字母?它会搅乱一切?或重音字母?且不说其他字母像俄罗斯西里尔和希腊字母和中国及... – RenniePet

+0

是的,这个假设是正确的。此解决方案仅适用于单字节(ASCII)字符,并且会迅速打破表情符号或国际字符等任何内容。 – dbart

0

有雨燕3.0的版本Martin R答案

public class UTF8Encoding { 
    public static func encode(bytes: Array<UInt8>) -> String { 
    var encodedString = "" 
    var decoder = UTF8() 
    var generator = bytes.makeIterator() 
    var finished: Bool = false 
    repeat { 
     let decodingResult = decoder.decode(&generator) 
     switch decodingResult { 
     case .scalarValue(let char): 
     encodedString += "\(char)" 
     case .emptyInput: 
     finished = true 
     case .error: 
     finished = true 
     } 
    } while (!finished) 
    return encodedString 
    } 
    public static func decode(str: String) -> Array<UInt8> { 
    var decodedBytes = Array<UInt8>() 
    for b in str.utf8 { 
     decodedBytes.append(b) 
    } 
    return decodedBytes 
    } 
} 

如果你想显示从UTF-8字符串的表情符号,只是用户convertEmojiCodesToString低于方法。这是正常的像“U + 1F52B”(表情符)的字符串或“U + 1F1E6 U + 1F1F1”(国国旗的表情符号)

class EmojiConverter { 
    static func convertEmojiCodesToString(_ emojiCodesString: String) -> String { 
    let emojies = emojiCodesString.components(separatedBy: " ") 
    var resultString = "" 
    for emoji in emojies { 
     var formattedCode = emoji 
     formattedCode.slice(from: 2, to: emoji.length) 
     formattedCode = formattedCode.lowercased() 
     if let charCode = UInt32(formattedCode, radix: 16), 
     let unicode = UnicodeScalar(charCode) { 
     let str = String(unicode) 
     resultString += "\(str)" 
     } 
    } 
    return resultString 
    } 
} 
1

斯威夫特3

let s = String(bytes: arr, encoding: .utf8)

1

如果您从原始缓冲区开始,例如从文件句柄返回的数据对象(在本例中,取自管道对象):

let data = pipe.fileHandleForReading.readDataToEndOfFile() 
var unsafePointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count) 

data.copyBytes(to: unsafePointer, count: data.count) 

let output = String(cString: unsafePointer)