# Coder avec Unicode/Conversion

Le texte
* Structure de donnée
* Conventions
* Conversion
* Normalisation
* Équivalence
Les interfaces
* L' accès aux fichiers 𝓌
* Passage de paramètres ⺇
* Entrées & sorties ϐ
* Entrées & sorties ϐ
* Interfaces graphiques et web ϐ
Les algorithmes
Annexes
* Glossaire A
* Autres lectures sur Unicode 📖
Le texte
* Structure de donnée
* Conventions
* Conversion
* Normalisation
* Équivalence
Les interfaces
* L' accès aux fichiers 𝓌
* Passage de paramètres ⺇
* Entrées & sorties ϐ
* Entrées & sorties ϐ
* Interfaces graphiques et web ϐ
Les algorithmes
Annexes
* Glossaire A
* Autres lectures sur Unicode 📖
[ Modifier le sommaire ]
De nos jours, les principales conversions que l'on doit faire sont des conversions entre utf-8 et utf-16, mais certains systèmes utilisent des encodages plus anciens. Il est alors nécessaire de les convertir. Cela ne peut se faire que si l'on sait quel est l'ancien encodage utilisé...
Si les données en entrée ne sont pas valides, une erreur de conversion d'encodage peut se produire.

## Perl

Exemple

## PHP

Sur une page Web, si default_charset = "UTF-8" n'est pas décommenté dans PHP.ini, si $chaine = '&eacute é $ €<br/>'; :
| PHP | print '<meta charset="UTF-8" />'; | print '<meta charset="iso-8859-1" />'; |
| print htmlentities($chaine); | &eacute é $ €<br/> | &eacute é $ €<br/> |
| print html_entity_decode($chaine); | é é $ € | é Ã© $ â‚¬ |
| print htmlspecialchars_decode($chaine); | é é $ € | é Ã© $ â‚¬ |
| print htmlspecialchars($chaine); | &eacute é $ €<br/> | &eacute Ã© $ â‚¬<br/> |
| print htmlentities($chaine, ENT_NOQUOTES, 'UTF-8'); | &eacute é $ €<br/> | &eacute é $ €<br/> |
| print html_entity_decode($chaine, ENT_NOQUOTES, "UTF-8"); | é é $ € | é Ã© $ â‚¬ |
| print htmlspecialchars_decode(htmlentities($chaine, ENT_NOQUOTES, 'UTF-8')); | é é $ € | é é $ € |
| print mb_convert_encoding($chaine, 'ISO-8859-1'); (anciennement print utf8_decode($chaine)) | é � $ ? | é é $ ? |
| print mb_convert_encoding($chaine, 'UTF-8'); (anciennement print utf8_encode($chaine)) | é Ã© $ â¬ | é ÃƒÂ© $ Ã¢Â‚Â¬ |
| print mb_convert_encoding($chaine, 'HTML-ENTITIES', 'UTF-8'); | é é $ € | ... |
| print mb_convert_encoding($chaine, 'UTF-8', 'auto'); | TODO |
| print mb_convert_encoding($chaine, 'ASCII', 'auto'); | TODO |
| print json_encode($chaine); | é \u00e9 $ \u20ac | ... |
| print json_decode($chaine); | | ... |
| print json_encode($chaine, JSON_UNESCAPED_UNICODE); | é é $ € | ... |
| print urlencode($chaine); | %26eacute+%C3%A9+%24+%E2%82%AC%3Cbr%2F%3E | ... |
| print rawurlencode($chaine); | %26eacute%20%C3%A9%20%24%20%E2%82%AC%3Cbr%2F%3E | ... |
| print urldecode($chaine); | é é $ € | ... |
| iconv('UTF-8', 'ASCII//IGNORE', $chaine) | TODO |
| mb_encode_mimeheader($chaine, 'UTF-8') | TODO |
Un substr('aàb', 2, 1) peut donner "à" car il compte pour deux caractères, pour avoir "b" il faut utiliser mb_substr('aàb', 2, 1) (pour multi-bytes substring).
Pour échapper les symboles Unicode indigestes comme "U+001F" :

### Base de données

Insertion dans une base MySQL avec MySQLi :
Insertion dans une base MySQL avec PDO :

## Python
### Exemple de conversion

Conversion d'une chaîne Unicode en une chaîne utf-8; cas de la chaîne « âäàéèëê » :
En Python 3 :
Exemple de création d'un caractère à partir de sa forme encodée en UTF-16 :
Exemple de conversion d'un caractère non latin dans un codage UTF8 ou UTF-16 :

### Gestion des erreurs de conversion

En Python 2, le codage des chaînes littérales dépend de l'environnement logiciel utilisé, dans le cas d'un système Windows.
L'exemple suivant créera donc des erreurs différentes en fonction de l'environnement d'exécution.
Le message d'erreur «UnicodeDecodeError: 'utf8' codec can't decode byte 0x82 in position 8: invalid start byte» donne deux indications: le contexte de l'erreur et l'erreur elle même.
* Le contexte de l'erreur: «'utf8' codec can't decode byte 0x82 in position 8» signifie que lors de la lecture d'une chaîne qui devrait être en utf8 «'utf8' codec» l'octet 0x82 a été rencontrée dans la chaîne d'origine.
* L'erreur: «invalid start byte» indique que l'octet rencontré, ici 0x82, n'est pas un octet qui peut marquer le début d'un caractère, ici en utf8.
| Code | Erreur | Explication | Correction des données | Correction du code |
| print chaine.decode("utf8") | UnicodeDecodeError: 'utf8' codec can't decode byte 0x82 in position 8: invalid start byte | Dans la chaîne de départ, à la position 8, se trouve "é". L'octet 0x82 est précisément le codage de ce caractère dans la page de code 850. | S'il faut décoder de l'utf8, les données ne devraient pas être codées en code page 850. | Si au contraire l'encodage utilisé dans des données source doit être du codepage 850, il serait plus logique d'utiliser decode("cp850") plutôt que decode("utf8") |
| print chaine.encode("utf8") | UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 8: ordinal not in range(128) | Dans la chaîne de départ, à la position 8, se trouve "é". L'octet 0xc3 est précisément le premier des deux octets utf8 nécessaire au codages de certains caractères latins accentués en utf8. Lors de la lecture d'une chaîne ascii, les caractères devraient avoir une valeur inférieure à 128 (0x80) ce qui n'est pas le cas ici. Il faut comprendre que pour encoder un texte sous la forme d'une séquence d'octet, la méthode encode s'attend vraisemblablement à avoir une chaîne unicode en entrée, ce qui peut supposer un appel implicite à la méthode decode de manière à convertir la chaîne d'octet en un texte avec l'encodage par défaut, qui ici semble être l'ascii. | Pour utiliser la méthode encode, il faut que la donnée en entrée soit de type unicode. | Si les données d'entrées doivent être de type chaîne d'octets, il ne faut pas utiliser la méthode encode. Cette méthode a d'ailleurs été supprimée de la classe chaîne d'octets en Python3.. |
| print chaine.decode("utf8") | UnicodeEncodeError: ' ascii' codec can't encode character u'\xe9' in position 8: ordinal not in range(128) | Dans la chaîne de départ, à la position 8, se trouve le caractère unicode «é» (qui porte bien le numéro U+00e9 en unicode. Lors de la lecture d'une chaîne ascii, les caractères devraient avoir une valeur inférieure à 128 (0x80) ce qui n'est pas le cas ici. | La méthode decode sert à décoder des chaînes d'octets, dans ce cas les données d'entrée doivent être une chaîne d'octet et non un texte unicode. | Si les données d'entrées doivent être de type unicode, il ne faut pas utiliser la méthode decode. Cette méthode a d'ailleurs été supprimée de la classe unicode en Python3.. |

## Java

En Java, les chaînes de caractères sont déjà Unicode ; le constructeur de la classe java.lang.String permet de décoder une séquence d'octets. La méthode getBytes de cette classe permet d'obtenir les octets d'encodage.

## JavaScript

JavaScript propose les fonctions "encodeURI" et "decodeURI".
Sinon, une astuce car la conversion UTF8 n'est pas native consiste à :

## Vala

En Vala, le type string utilise des données au format utf-8. Les données qui ne sont pas à ce format peuvent être mises à ce format à l'aide de la classe CharsetConverter.
Exemple:

## PL/SQL

En PL/SQL des erreurs de conversion peuvent être remplacées par des caractères blancs

## Notes

* ↑ http://php.net/manual/fr/function.mb-substr.php
* ↑ https://magp.ie/2011/01/06/remove-non-utf8-characters-from-string-with-php/
* ↑ stackoverflow.com/questions/447107/what-is-the-difference-between-encode-decode
* ↑ stackoverflow.com/questions/447107/what-is-the-difference-between-encode-decode
* ↑ https://www.w3schools.com/jsref/jsref_decodeuri.asp
* ↑ http://ecmanaut.blogspot.fr/2006/07/encoding-decoding-utf8-in-javascript.html
* ↑ docs.oracle.com/cd/B19306_01/server.102/b14225/ch7progrunicode.htm

## Voir aussi

* http://fr.openclassrooms.com/informatique/cours/passer-du-latin1-a-l-unicode/preparer-php