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)
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")
}
Solution rapide
array.reduce("", combine: { $0 + String(format: "%c", $1)})
Représentation Hex:
array.reduce("", combine: { $0 + String(format: "%02x", $1)})
Cela a fonctionné pour moi:
String(bytes: bytes, encoding: NSUTF8StringEncoding)
Cette solution fonctionne.
NSString(bytes: data!, length: data!.count, encoding: NSUTF8StringEncoding)
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)!
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.
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)"
}
}
}
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'
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.
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!
"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))
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")
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)