arrays - for - swift array filter
Cómo convertir la matriz de bytes UInt8 a cadena en Swift (13)
"MSString (bytes:, longitud:, codificación:)" no parece estar funcionando a partir del 26 de julio de 2015
Convertir los valores de byte a ASCII parece problemático, si has golpeado un muro, puedes hacerlo de la siguiente manera (y quizás me esté perdiendo algo con swift pero no pude encontrar ninguna solución dentro de mi período de tiempo). Esto se hará con dos funciones La primera función acepta un UInt8 y lo convierte en una representación "/ u {}", que luego devuelve la función. En segundo lugar, se configura otra función que toma una matriz UInt8 como parámetro y luego genera una cadena.
Paso 1. Función convertir cada byte a "/ 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}"
// .. Agregar para tantos caracteres como anticipes ... no olvides base 16 ..
case 0x09: characterToReturn = "/u{09}"
case 0x0A: characterToReturn = "/u{0A}"
default: characterToReturn = "/u{0}"
/ * .. y hasta 0xff * /
case 0xFE: characterToReturn = "/u{FE}"
case 0xFF: characterToReturn = "/u{FF}"
}
return characterToReturn
}
Paso # 2 ... A continuación, una función que toma una matriz UInt8 como parámetro y luego devuelve una cadena ...
func UInt8ArrayToString(#UInt8Array: [UInt8]) -> String {
var returnString : String = ""
for eachUInt8Byte in UInt8Array {
returnString += convertToCharacter(UInt8Bits: eachUInt8Byte)
}
return returnString
}
Esto debería funcionar en un Swift Playground.
var myArray: [UInt8] = [0x30, 0x3A, 0x4B]
// Luego aplica las funciones de arriba
println (UInt8ArrayToString (UInt8Array: myArray))
Estoy enfrentando problemas al convertir la matriz de bytes UInt8
en una cadena en swift. He buscado y encuentro una solución sencilla.
String.stringWithBytes(buff, encoding: NSUTF8StringEncoding)
pero muestra el error String.type
no tiene un miembro stringWithBytes
. ¿Alguien puede sugerirme una solución?
este es mi código donde NSData
un NSData
y lo convierto en una matriz de bytes y luego tengo que convertir esa matriz de bytes en una cadena.
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)
Aquí hay un código más generalizado para extraer cadenas de una matriz de bytes donde las cadenas se han codificado 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)!
}
}
Este es un extracto de una clase más grande (consulte también https://.com/a/41547936/253938 ) que utilizo para procesar datos serializados.
Ejemplo completo para Swift 2 y 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''
Esta solución funciona.
NSString(bytes: data!, length: data!.count, encoding: NSUTF8StringEncoding)
Esto funcionó para mí:
String(bytes: bytes, encoding: NSUTF8StringEncoding)
Martin R en https://.com/a/29644387/2214832 respondió a Sunil Kumar sobre su problema, pero no sobre la pregunta del tema. El problema sigue apareciendo si ya tiene una matriz de bytes UInt8 y necesita presentarla como una cadena.
Aquí está mi solución:
extension String {
init(_ bytes: [UInt8]) {
self.init()
for b in bytes {
self.append(UnicodeScalar(b))
}
}
}
Usando esta extensión, ahora puede iniciar Cadena con la matriz de bytes UInt8 así:
func testStringUInt8Extension() {
var cs : [UInt8] = []
for char : UInt8 in 0..<255 {
cs.append(char)
}
print("0..255 string looks like /(String(cs)))")
}
Esta no es la solución ideal porque prácticamente necesitarías decodificar algo así como el texto codificado en UTF-8. Pero para datos ASCII esto funciona como se esperaba.
No muy elegante o ''Swifty'', pero esto es simple y funciona:
let i: UInt8 = 65
let s = String(format: "%c", i) // A
¡Perdí horas buscando una manera fácil de hacer esto, antes de que de repente pensara en ''printf'' de mis días de scripting en Unix!
Para cualquier persona que no pueda transformar una matriz de bytes en una cadena, intente esto
String(data: Data(decrypted), encoding: .utf8)
Este es mi ejemplo de extensión de cadena. Lo uso para 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)"
}
}
}
Primero necesita convertir la matriz Int8 a Datos, luego convertir a Cadena.
Esta es mi solución:
var buffer = [Int8](repeating: 0, count: 100)
let data = Data(bytes: buffer as [Int8], count: buffer.count);
return String( data: data, encoding: .utf8)
Solución swifty
array.reduce("", combine: { $0 + String(format: "%c", $1)})
Representación hexagonal:
array.reduce("", combine: { $0 + String(format: "%02x", $1)})
Actualización para Swift 3 / Xcode 8:
Cadena de bytes: [UInt8]
:
if let string = String(bytes: bytes, encoding: .utf8) {
print(string)
} else {
print("not a valid UTF-8 sequence")
}
Cadena de data: Data
:
let data: Data = ...
if let string = String(data: data, encoding: .utf8) {
print(string)
} else {
print("not a valid UTF-8 sequence")
}
Actualización para Swift 2 / Xcode 7:
Cadena de bytes: [UInt8]
:
if let string = String(bytes: bytes, encoding: NSUTF8StringEncoding) {
print(string)
} else {
print("not a valid UTF-8 sequence")
}
Cadena de data: NSData
:
let data: NSData = ...
if let str = String(data: data, encoding: NSUTF8StringEncoding) {
print(str)
} else {
print("not a valid UTF-8 sequence")
}
Respuesta anterior:
String
no tiene un método stringWithBytes()
. NSString
tiene un
NSString(bytes: , length: , encoding: )
método que podría usar, pero puede crear la cadena directamente desde NSData
, sin la necesidad de una matriz UInt8
:
if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
println(str)
} else {
println("not a valid UTF-8 sequence")
}
Swift 3
lo siguiente me estaba dando un error debido a "NSUTF8StringEncoding":
String(data: nsdata, encoding: NSUTF8StringEncoding)!
esto me funcionó en swift 3:
let xmlStr:String = String(bytes: data!, encoding: String.Encoding.utf8)!
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")