web-dev-qa-db-fra.com

Comment convertir un tableau d'octets UInt8 en chaîne in Swift

Je rencontre des problèmes lors de la conversion UInt8 Tableau d'octets en chaîne dans Swift. J'ai cherché et trouvé une solution simple

String.stringWithBytes(buff, encoding: NSUTF8StringEncoding)

mais il montre l'erreur String.type n'a pas de membre stringWithBytes. Quelqu'un peut-il me proposer une solution?

c'est mon code où je reçois un NSData et que je convertis en tableau d'octets, puis je dois convertir ce tableau d'octets en chaîne.

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)
43
Sunil Kumar

Mise à jour pour Swift 3/Xcode 8:

Chaîne de bytes: [UInt8]:

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

Chaîne de data: Data:

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

Mise à jour pour Swift 2/Xcode 7:

Chaîne de bytes: [UInt8]:

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

Chaîne de data: NSData:

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

Réponse précédente:

String n'a pas de méthode stringWithBytes(). NSString a un

 NSString(bytes: , length: , encoding: )

méthode que vous pouvez utiliser, mais vous pouvez créer la chaîne directement à partir de NSData, sans avoir besoin d'un tableau UInt8:

if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
    println(str)
} else {
    println("not a valid UTF-8 sequence")
}
68
Martin R

Solution rapide

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

Représentation Hex:

array.reduce("", combine: { $0 + String(format: "%02x", $1)})
9
Marek H

Cela a fonctionné pour moi:

String(bytes: bytes, encoding: NSUTF8StringEncoding)
9
david72

Cette solution fonctionne.

NSString(bytes: data!, length: data!.count, encoding: NSUTF8StringEncoding) 
5
niklas30

Swift

ce qui suit m'a donné une erreur en raison de "NSUTF8StringEncoding":

String(data: nsdata, encoding: NSUTF8StringEncoding)! 

cela a fonctionné pour moi dans Swift 3:

let xmlStr:String = String(bytes: data!, encoding: String.Encoding.utf8)!
4
LeftyT

Martin R in https://stackoverflow.com/a/29644387/2214832 a répondu à Sunil Kumar sur son problème mais pas sur la question du sujet. Le problème persiste si vous avez déjà un tableau d'octets UInt8 et devez le présenter sous forme de chaîne.

Voici ma solution:

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

En utilisant cette extension, vous pouvez maintenant init String avec le tableau d'octets UInt8 comme ceci:

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

Ce n'est pas la solution idéale, car vous devriez pratiquement décoder quelque chose comme du texte codé en UTF-8. Mais pour les données ASCII), cela fonctionne comme prévu.

4
ACHTUNG

Pour ceux qui ne peuvent pas transformer un tableau d'octets en chaîne, essayez ceci

String(data: Data(decrypted), encoding: .utf8)

Ceci est mon exemple d'extension de chaîne. Je l'utilise pour AES

extension String {

    func decryptAES(key: String, iv: String) -> String {
        do {
            let encrypted = self
            let key = Array(key.utf8)
            let iv = Array(iv.utf8)
            let aes = try AES(key: key, blockMode: CTR(iv: iv), padding: .noPadding)
            let decrypted = try aes.decrypt(Array(hex: encrypted))
            return String(data: Data(decrypted), encoding: .utf8) ?? ""
        } catch {
            return "Error: \(error)"
        }
    }
}
3

Exemple complet pour 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'
2
Lightbeard

Voici un code plus généralisé pour extraire les chaînes d'un tableau d'octets où les chaînes ont été codées en UTF-8.

/// 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)!
   }
}

Il s’agit d’un extrait d’une classe plus importante (voir aussi https://stackoverflow.com/a/41547936/253938 ) que j’utilise pour traiter des données sérialisées.

2
RenniePet

Pas très élégant ou 'Swifty', mais c'est simple et ça marche:

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

J'ai perdu des heures à chercher un moyen facile de le faire, avant de penser soudain à 'printf' à partir de mes jours de scripting Unix!

2
Simon Youens

"MSString (octets:, longueur:, codage:)" ne semble pas fonctionner au 26 juillet 2015

La conversion des valeurs d'octets en ASCII semble problématique, si vous avez heurté un mur, vous pouvez le faire comme suit (et il se peut que je manque quelque chose avec Swift mais je n’ai trouvé aucune solution dans les délais impartis).) La première fonction accepte un UInt8 et le convertit en une représentation "\ u {}", qui est ensuite renvoyée par la fonction. une autre fonction est configurée qui prend un tableau UInt8 en tant que paramètre, puis génère une chaîne.

Étape 1. La fonction convertit chaque octet en "\ u {someNumber}"

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}"

// .. Ajoutez autant de caractères que vous le souhaitez ... n'oubliez pas la base 16 ..

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

default: characterToReturn = "\u{0}"

/ * .. et tout le chemin jusqu'à 0xff * /

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



  }

return characterToReturn

}

Étape n ° 2 ... Ensuite, une fonction qui prend un tableau UInt8 en tant que paramètre renvoie ensuite une chaîne ...

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

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

returnString += convertToCharacter(UInt8Bits: eachUInt8Byte)

}

return returnString}

Cela devrait fonctionner dans un Swift Playground Crée un tableau

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

// Puis applique les fonctions ci-dessus

println (UInt8ArrayToString (UInt8Array: myArray))

1
RobertHana

Swift 4/Ubuntu 16.04

let serverAns = [UInt8](repeating: 0x50, count: 100)
let readBytes = 8
let truncatedServerAns = serverAns[0..<readBytes]
let tsaData = Data(bytes: truncatedServerAns)
let serverIdStr = String(data: tsaData, encoding: .utf8)
print("serverIdStr=\(String( describing: serverIdStr))")

// Prints:
// serverIdStr=Optional("PPPPPPPP")
0
PJ_Finnegan

Vous devez d’abord convertir le tableau Int8 en données, puis le convertir en chaîne.

Ceci est ma solution:

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