2015-12-04 2 views
1

Я знаю, что такие вопросы существуют как в переполнении стека, так и в другом месте. Но, похоже, он развился очень много.Swift 2.1 [UInt8] --utf8 -> String?

Меня особенно интересует метод, который не использует NSData/NSString, поскольку, если Санта принесет Swift в мир Linux, он, без сомнения, будет без библиотек NS, и я хотел бы знать, как делайте это только в Swift.

+0

Почему это дублируется? Они явно используют NSString и NSData. Я заявил, что после решения, которое не использовало ни того, ни другого. –

ответ

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) 
4

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 Data { 
    var string: String { return String(data: self, 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

Я на самом деле в конечном итоге необходимости делать это для потока 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) 
+1

Здесь http://stackoverflow.com/a/24757284/1187415 является общим расширением строки, которое строит строку из любой последовательности UTF-8/16/32, например. 'let s = String.init (codeUnits: utf8stream, codec: UTF8())'. –

+0

Большое вам спасибо за такое большое расширение! Сделал более общую версию: 'init (utf8stream: T) {', и это позволило мне использовать 'ArraySlice', что было очень полезно для меня, мне нужно было проанализируйте очень длинный массив 'UInt8' для создания большого количества строк, поэтому вызов init с ArraySlice намного быстрее, чем выделение массива из этого фрагмента. –

Смежные вопросы