Re: encoding encoding ...

Top Page

Reply to this message
Author: gedeon.legaut
Date:  
To: guilde
Subject: Re: encoding encoding ...
Merci Edgar !
Je suis arrivé à tes conclusions mais ... en plus de temps !

<programme>
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def repr_bin2(s, coding) :
    return ''.join('{0:08b}'.format(c) for c in s.encode(coding))
def binaire_to_utf8 (s) :
    return "".join([chr(int(s[i:i+8],2)) for i in range(0,len(s),8)])
s = 'Je me suis vrillé les neurones avec UTF8 !'
print(s.encode('utf-8'))
print(repr_bin2(s, 'utf8'))
binaire = repr_bin2(s, 'utf8')
sp = binaire_to_utf8 (binaire)
print(sp)
print(bytes(sp,'latin_1').decode('utf-8'))
</programme>


ce qui donne

<terminal>
b'Je me suis vrill\xc3\xa9 les neurones avec UTF8 !'
01001010011001010010000001101101011001010010000001110011011101010110100101110011001000000111011001110010011010010110110001101100110000111010100100100000011011000110010101110011001000000110111001100101011101010111001001101111011011100110010101110011001000000110000101110110011001010110001100100000010101010101010001000110001110000010000000100001
Je me suis vrillé les neurones avec UTF8 !
Je me suis vrillé les neurones avec UTF8 !
</terminal>

Effectivement, comme le 'é' est encodé sur 2 octets, et que j'ai découpé les octets en deux avec le "for c in s.encode(coding)", cela m'oblige effectivement à la fin à convertir en bytes(sp,'latin_1') puis à décoder en utf8.

<fonction>
def utf8_to_binaire (s) :
    sb = ""
    for c in s :
        sb += bin(ord(c))[2:]
    return sb
</fonction>


Avec cette fonction,j'évite le "for c in s.encode(coding)" pour un "for c in s" : là, j'encode directement le 'é' d'un seul bloc.
Je me suis "amusé" à écrire une fonction python qui prend en argument une chaîne de caractère qui présente ces problèmes de type é et qui fait la correction :

<programme>
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

s = 'indépendant du possède une propriété de non-rivalité (elle ne se détruit'

def traitement_recursif(s) :
    if len(s) == 0 :
        return ''
    else :
        index = -1
        for i in range(len(s)) :
            if ord(s[i]) > 127 :
                index = i
                break
        #print(index)
        if index == -1 :
            index = len(s)
        ch = s[index:index+2]
        return s[:index] + bytes(ch, 'latin_1').decode('utf-8') + traitement_recursif(s[index+2:])


print(s)
print(traitement_recursif(s))

# écrit le résultat dans le fichier "a"
fichier = open('a','w')
fichier.write(s+'\n')
fichier.write(traitement_recursif(s))
fichier.close()
</programme>

ce qui donne

<terminal>
indépendant du possède une propriété de non-rivalité (elle ne se détruit
indépendant du possède une propriété de non-rivalité (elle ne se détruit
</terminal>

Merci de vos réponses !
Gédéon Légaut


----- Mail original -----
De: "Edgar Bonet" <guilde@???>
À: guilde@???
Envoyé: Jeudi 27 Février 2020 18:09:36
Objet: Re: encoding encoding ...

Re!

Gédéon Légaut a écrit :
> tu m'as mis le doute quand j'ai vu : Gédéon Légaut a écrit ;-)


C'était une référence à de la littérature jeunesse. ;-) [1]

> <programme python>[...]


Bon, je ne connais rien à Python, mais je crois que je devine le
problème.

Dès qu'on code les caractères avec plus de 8 bits, il faut bien
distinguer les octets et les caractères. Et donc aussi les tableaux
d'octets (« byte array » en anglais) et les chaînes de caractères
(« string »). La fonction chr(), à son nom, on devine qu'elle sert à
générer des caractères. Et de fait :

    $ python3 -q
    >>> chr(0xc3)
    'Ã'
    >>> chr(0xa9)
    '©'
    >>> 


La fonction binaire_to_utf8() découpe une chaîne de bits par groupes
de 8 (donc des octets) et interprète chaque octet comme un caractère
ayant pour numéro de code (« code point ») la valeur numérique de
l'octet. En d'autres mots elle interprète la séquence d'octets comme une
chaîne en ISO-Latin-1 : codage identité dans [0..255].

Ce que tu veux c'est plutôt générer un tableau d'octets (byte array). Je
ne sais pas comment on fait ça en Python. Ensuite tu peux sortir le
tableau d'octets tel quel sur la console en mode binaire, ou bien
demander à Python de l'interpréter comme un texte codé en UTF-8.

Il faudrait des connaisseurs en Python pour te guider plus loin.

À+,

Edgar.

[1] https://www.apprendre-en-ligne.net/bloginfo/index.php/2009/01/21/151-martine-ecrit-en-utf-8