Swift'de string'e UInt8 bayt dizisini dönüştürme

UInt8 Byte dizisini hızlıca dizeye dönüştürürken sorunlarla karşılaşıyorum. Aradım ve basit bir çözüm buldum

String.stringWithBytes(buff, encoding: NSUTF8StringEncoding)

ancak String.type stringWithBytes adlı bir üyeye sahip değil. Birisi bana bir çözüm önerebilir mi?

Bu benim NSData </​​code> alıyorum ve bayt dizisine dönüştürdüğüm ve bu bayt dizisini dizeye dönüştürmem gereken kodum.

let count = data.length/sizeof(UInt8)
var array = [UInt8](count: count, repeatedValue: 0)
data.getBytes(&array, length:count * sizeof(UInt8))
String.stringWithBytes(buff, encoding: NSUTF8StringEncoding)
24
stackoverflow.com/a/24465772/986169 bu size yardımcı olabilir
katma yazar giorashc, kaynak

14 cevap

Update for Swift 3/Xcode 8:

bayttan dize: [UInt8] :

if let string = String(bytes: bytes, encoding: .utf8) {
    print(string)
} else {
    print("not a valid UTF-8 sequence")
}

verileri dizesi: Veri :

let data: Data = ...
if let string = String(data: data, encoding: .utf8) {
    print(string)
} else {
    print("not a valid UTF-8 sequence")
}

Update for Swift 2/Xcode 7:

bayttan dize: [UInt8] :

if let string = String(bytes: bytes, encoding: NSUTF8StringEncoding) {
    print(string)
} else {
    print("not a valid UTF-8 sequence")
}

data dizgisi: NSData </​​code>:

let data: NSData = ...
if let str = String(data: data, encoding: NSUTF8StringEncoding) {
    print(str)
} else {
    print("not a valid UTF-8 sequence")
}

Önceki cevap:

String does not have a stringWithBytes() method. NSString has a

 NSString(bytes: , length: , encoding: )

Kullanabileceğiniz yöntem, ancak UInt8 dizisine gerek olmadan dizeyi doğrudan NSData </​​code> 'dan oluşturabilirsiniz:

if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
    println(str)
} else {
    println("not a valid UTF-8 sequence")
}
46
katma
@RudolfJ: Asıl cevabım hem "bytes to String" hem de "String'e veri" (yani OP'ye gereken veri) içindi. Daha sonra Swift 2 ve 3 için sadece "String'e veri" kodunu güncelledim - Şimdi karışıklığı önlemek için Swift 2 ve 3 için "bytes to String" dönüşümlerini de ekledi.
katma yazar Martin R, kaynak
Bu benim için çalışmıyor. Dize (data: xxx, kodlama: NSUTF8StringEncoding) Veriyi bir değişken olarak alır, bir [Uint8] değil
katma yazar Rudolf J, kaynak
Teşekkürler @MartinR!
katma yazar Rudolf J, kaynak
Swift 4.1: 'bytes' bir [UTF8] dizisi olduğu String (bayt: bayt, kodlama: .utf8) demeliyim.
katma yazar AbePralle, kaynak

Update for Swift 3/Xcode 8:

bayttan dize: [UInt8] :

if let string = String(bytes: bytes, encoding: .utf8) {
    print(string)
} else {
    print("not a valid UTF-8 sequence")
}

verileri dizesi: Veri :

let data: Data = ...
if let string = String(data: data, encoding: .utf8) {
    print(string)
} else {
    print("not a valid UTF-8 sequence")
}

Update for Swift 2/Xcode 7:

bayttan dize: [UInt8] :

if let string = String(bytes: bytes, encoding: NSUTF8StringEncoding) {
    print(string)
} else {
    print("not a valid UTF-8 sequence")
}

data dizgisi: NSData </​​code>:

let data: NSData = ...
if let str = String(data: data, encoding: NSUTF8StringEncoding) {
    print(str)
} else {
    print("not a valid UTF-8 sequence")
}

Önceki cevap:

String does not have a stringWithBytes() method. NSString has a

 NSString(bytes: , length: , encoding: )

Kullanabileceğiniz yöntem, ancak UInt8 dizisine gerek olmadan dizeyi doğrudan NSData </​​code> 'dan oluşturabilirsiniz:

if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
    println(str)
} else {
    println("not a valid UTF-8 sequence")
}
46
katma
@RudolfJ: Asıl cevabım hem "bytes to String" hem de "String'e veri" (yani OP'ye gereken veri) içindi. Daha sonra Swift 2 ve 3 için sadece "String'e veri" kodunu güncelledim - Şimdi karışıklığı önlemek için Swift 2 ve 3 için "bytes to String" dönüşümlerini de ekledi.
katma yazar Martin R, kaynak
Bu benim için çalışmıyor. Dize (data: xxx, kodlama: NSUTF8StringEncoding) Veriyi bir değişken olarak alır, bir [Uint8] değil
katma yazar Rudolf J, kaynak
Teşekkürler @MartinR!
katma yazar Rudolf J, kaynak
Swift 4.1: 'bytes' bir [UTF8] dizisi olduğu String (bayt: bayt, kodlama: .utf8) demeliyim.
katma yazar AbePralle, kaynak

Hızlı çözüm

array.reduce("", combine: { $0 + String(format: "%c", $1)})

Altıgen gösterimi:

array.reduce("", combine: { $0 + String(format: "%02x", $1)})
7
katma
azaltmak IMO ise hatalı kullanım. array.map {String (biçim: "% c", $ 0)} .joined() ile giderdim.
katma yazar Tim Vermeulen, kaynak
Swift 3: array.reduce ("", {$ 0 + String (biçim: "% c", 1 $)})
katma yazar AbdulMomen عبدالمؤمن, kaynak

Hızlı çözüm

array.reduce("", combine: { $0 + String(format: "%c", $1)})

Altıgen gösterimi:

array.reduce("", combine: { $0 + String(format: "%02x", $1)})
7
katma
azaltmak IMO ise hatalı kullanım. array.map {String (biçim: "% c", $ 0)} .joined() ile giderdim.
katma yazar Tim Vermeulen, kaynak
Swift 3: array.reduce ("", {$ 0 + String (biçim: "% c", 1 $)})
katma yazar AbdulMomen عبدالمؤمن, kaynak

Bu benim için çalıştı:

String(bytes: bytes, encoding: NSUTF8StringEncoding)
6
katma

Bu çözüm işe yarıyor.

NSString(bytes: data!, length: data!.count, encoding: NSUTF8StringEncoding) 
4
katma

Swift 3

Aşağıdaki "NSUTF8StringEncoding" nedeniyle bana bir hata veriyordu:

String(data: nsdata, encoding: NSUTF8StringEncoding)! 

Bu benim için hızlı bir şekilde 3 çalıştı:

let xmlStr:String = String(bytes: data!, encoding: String.Encoding.utf8)!
3
katma

Martin R, https://stackoverflow.com/a/29644387/2214832 , Sunil Kumar’ı sorununa değil, konu sorusu. Sorun, UInt8 bayt dizisine zaten sahipseniz ve dizgi olarak sunmanız gerekiyorsa görüntülenir.

İşte benim çözümüm:

extension String {
    init(_ bytes: [UInt8]) {
        self.init()
        for b in bytes {
            self.append(UnicodeScalar(b))
        }
    }
}

Bu uzantıyı kullanarak, şu şekilde UInt8 bayt dizisine sahip String dizisini başlatabilirsiniz:

func testStringUInt8Extension() {
    var cs : [UInt8] = []
    for char : UInt8 in 0..<255 {
        cs.append(char)
    }
    print("0..255 string looks like \(String(cs)))")
}

Bu ideal bir çözüm değildir çünkü pratik olarak UTF-8 kodlu metin gibi bir şeyi çözmeniz gerekir. Ancak ASCII verileri için bu beklendiği gibi çalışır.

3
katma

Burada, dizelerin UTF-8'de kodlandığı bir bayt dizisinden dizeleri ayıklamak için daha genelleştirilmiş bir kod verilmiştir.

/// Class which encapsulates a Swift byte array (an Array object with elements of type UInt8) and an
/// index into the array.
open class ByteArrayAndIndex {

   private var _byteArray : [UInt8]
   private var _arrayIndex = 0

   public init(_ byteArray : [UInt8]) {
      _byteArray = byteArray;
   }

   /// Method to get a UTF-8 encoded string preceded by a 1-byte length.
   public func getShortString() -> String {
      return getTextData(getUInt8AsInt())
   }

   /// Method to get a UTF-8 encoded string preceded by a 2-byte length.
   public func getMediumString() -> String {
      return getTextData(getUInt16AsInt())
   }

   /// Method to get a UTF-8 encoded string preceded by a 4-byte length. By convention a length of
   /// -1 is used to signal a String? value of nil.
   public func getLongString() -> String? {
      let encodedLength = getInt32()
      if encodedLength == -1 {
         return nil
      }
      return getTextData(Int(encodedLength))
   }

   /// Method to get a single byte from the byte array, returning it as an Int.
   public func getUInt8AsInt() -> Int {
      return Int(getUInt8())
   }

   /// Method to get a single byte from the byte array.
   public func getUInt8() -> UInt8 {
      let returnValue = _byteArray[_arrayIndex]
      _arrayIndex += 1
      return returnValue
   }

   /// Method to get a UInt16 from two bytes in the byte array (little-endian), returning it as Int.
   public func getUInt16AsInt() -> Int {
      return Int(getUInt16())
   }

   /// Method to get a UInt16 from two bytes in the byte array (little-endian).
   public func getUInt16() -> UInt16 {
      let returnValue = UInt16(_byteArray[_arrayIndex]) |
                        UInt16(_byteArray[_arrayIndex + 1]) << 8
      _arrayIndex += 2
      return returnValue
   }

   /// Method to get an Int32 from four bytes in the byte array (little-endian).
   public func getInt32() -> Int32 {
      return Int32(bitPattern: getUInt32())
   }

   /// Method to get a UInt32 from four bytes in the byte array (little-endian).
   public func getUInt32() -> UInt32 {
      let returnValue = UInt32(_byteArray[_arrayIndex]) |
                        UInt32(_byteArray[_arrayIndex + 1]) << 8 |
                        UInt32(_byteArray[_arrayIndex + 2]) << 16 |
                        UInt32(_byteArray[_arrayIndex + 3]) << 24
      _arrayIndex += 4
      return returnValue
   }

  //Method to decode UTF-8 encoded text data in the byte array.
   private func getTextData(_ numberBytes : Int) -> String {
      if numberBytes == 0 {
         return "" //Tiny optimization?
      }
      let startIndex = _arrayIndex
      _arrayIndex += numberBytes
      return String(bytes: _byteArray[startIndex ..< _arrayIndex], encoding: String.Encoding.utf8)!
   }
}

Bu, daha büyük bir sınıfa ait bir özettir (ayrıca bkz. https://stackoverflow.com/a/41547936/253938 ) Seri hale getirilmiş verileri işlemek için kullanıyorum.

1
katma

Complete example for Swift 2 & 3:

import Foundation

let bytes : [UInt8] = [72, 73]
let nsdata = NSData(bytes: bytes as [UInt8], length: 2)
let str = String(data: nsdata, encoding: NSUTF8StringEncoding)!//'HI'
1
katma

Çok zarif ya da 'Swifty' değil, ama bu basit ve işe yarıyor:

let i: UInt8 = 65
let s = String(format: "%c", i) //A

Bunu yapmak için kolay bir yol bulmak için saatler harcadım, aniden Unix komut dosyalarından 'printf' düşünmeden önce!

1
katma

Swift 4/Ubuntu 16.04

let serverAns = [UInt8](repeating: 0x50, count: 100)
let readBytes = 8
let truncatedServerAns = serverAns[0..
0
katma

"MSString (bayt:, uzunluk:, kodlama:)" 26 Temmuz 2015 itibariyle çalışıyor görünmüyor

ASCII'ye bayt değerlerini dönüştürmek sorunlu görünüyor, eğer bir duvara çarptıysanız bunu aşağıdaki gibi zor bir şekilde yapabilirsiniz (ve belki hızlı bir şekilde bir şeyleri özlüyorum ama zaman dilimim içinde herhangi bir çözüm bulamadım.) Bu işlem şu şekilde yapılacaktır: iki işlev. İlk işlev bir UInt8'i kabul eder ve bunu "\ u {}" temsiline dönüştürür ve bu da işlev tarafından döndürülür. İkincisi, bir UInt8 dizisini bir parametre olarak alan başka bir işlev ayarlanır, daha sonra bir dize çıktılanır.

Aşama 1. İşlev, her baytı "\ u {someNumber}" a dönüştürür

func convertToCharacters(#UInt8Bits : UInt8) -> String {

 var characterToReturn : String

 switch UInt8Bits{

case 0x00: characterToReturn = "\u{0}"
case 0x01: characterToReturn = "\u{1}"
case 0x02: characterToReturn = "\u{2}"
case 0x03: characterToReturn = "\u{3}"
case 0x04: characterToReturn = "\u{4}"

// .. Tahmin edeceğiniz kadar çok karakter ekleyin ... Unutmayın ..

case 0x09: characterToReturn = "\u{09}"
case 0x0A: characterToReturn = "\u{0A}"

default: characterToReturn = "\u{0}"

/ * .. ve her şeye kadar 0xff * /

case 0xFE: characterToReturn = "\u{FE}"
case 0xFF: characterToReturn = "\u{FF}"



  }

characterToReturn karakterini döndür

}

Adım # 2 ... Bir UInt8 dizisini parametre olarak alan bir işlev daha sonra bir dizge döndürür ...

func UInt8ArrayToString(#UInt8Array: [UInt8]) -> String {

var returnString : String = "" for eachUInt8Byte in UInt8Array {

returnString + = convertToCharacter (UInt8Bits: eachUInt8Byte)

}

return returnString }

Bu bir Swift Oyun Alanı'nda çalışmalı Bir dizi yap

var myArray: [Uint8] = [0x30, 0x3A, 0x4B]

// Sonra yukarıdaki işlevleri uygulayın

println (UInt8ArrayToString (UInt8Array: myArray))

0
katma
<�İ> "NSString (bayt:, uzunluk:, kodlama:) ifadenizi açıklar mısınız?" Çalışıyor görünmüyor ... "? - Xcode 7 beta 5 ile iki kez kontrol ettim ve hiçbir sorun bulunamadı.
katma yazar Martin R, kaynak
Onunla da bir sorun yaşıyorum. İki UInt8'in xor'unu yapıyoruz ve ortaya çıkan şey, xor sonucu uygun bir UInt8 döndürüyor, ancak NSString (bayt, ...) dizgeyi dönüştüremiyor. Playground'u kullanırsam ve base16 başlamasından önce sonuç veren dizeleri ayarlarsam, NSString (bayt, ...) çalışır.
katma yazar Josh, kaynak

Önce Int8 dizisini Veri'ye dönüştürmeniz ve daha sonra String'e dönüştürmeniz gerekir.

Bu benim çözümüm:

    var buffer = [Int8](repeating: 0, count: 100)
    let data = Data(bytes: buffer as [Int8], count: buffer.count);
    return String( data: data, encoding: .utf8)
0
katma