es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo decodificar cadenas que incluyen literales utf8 como ”\xc3\xa6” en Swift?

Pregunta de seguimiento a mi anterior hilo sobre literales UTF-8:

Se estableció que se pueden decodificar literales UTF-8 de cadenas de esta manera que incluyen exclusivamente literales UTF-8:


let s = "\xc3\xa6"
let bytes = s
.components(separatedBy: "\x")
// components(separatedBy:) produciría una cadena vacía como primer elemento
// porque la cadena comienza con "\x". Lo omitimos
.dropFirst()
.compactMap { UInt8($0, radix: 16) }
if let decoded = String(bytes: bytes, encoding: .utf8) {
print(decoded)
} else {
print("¡La secuencia UTF8 era inválida!")
}

Sin embargo, esto solo funciona si la cadena solo contiene literales UTF-8. Como estoy obteniendo una lista de nombres de Wi-Fi que contienen estos literales UTF-8, ¿cómo decodifico toda la cadena?

Ejemplo:


let s = "Este es un nombre de Wi-Fi \xc3\xa6 que incluye literales UTF-8 \xc3\xb8"

Con el resultado esperado:


print(s)

Este es un nombre de Wi-Fi æ que incluye literales UTF-8 ø

En Python hay una solución simple para esto:


contents = source_file.read()
uni = contents.decode('unicode-escape')
enc = uni.encode('latin1')
dec = enc.decode('utf-8')

¿Existe una manera similar de decodificar estas cadenas en Swift 5?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Sí, puedes usar el método String.decodeCString(_:as:repairingInvalidCodeUnits:) de Swift para decodificar la cadena.

    Aquí está el código actualizado:

    let s = "Este es un nombre de WiFi \\xc3\\xa6 que incluye literales UTF-8 \\xc3\\xb8"
    var charArray: [CChar] = Array(s.utf8CString.map {CChar($0)})
    if let decoded = String.decodeCString(&charArray, as: UTF8.self, repairingInvalidCodeUnits: true)?.result {
        print(decoded)
    } else {
        print("¡La secuencia UTF8 era inválida!")
    }
    

    La propiedad utf8CString convierte la cadena en una matriz nula-terminada de bytes UTF-8, que es el formato requerido por decodeCString(_:as:repairingInvalidCodeUnits:). El parámetro repairingInvalidCodeUnits se establece en true para corregir automáticamente cualquier unidad de código UTF-8 inválida. El resultado se convierte de nuevo en una String.

    Ten en cuenta que este enfoque supone que las secuencias de escape ya están formateadas correctamente para la codificación UTF-8. Si no es así, es posible que debas procesar la cadena previamente para convertirlas antes de usar este método.

Comments are closed.