FreeToGenerate.com

Un fichier .properties n’a pas d’encodage propre : c’est le chargeur qui décide, et les deux chargeurs ne s’accordent pas. Rien n’est envoyé.

Essayez :

Vous le saisissez ici sous forme de texte et la page l’encode en UTF-8, ce qu’enregistre n’importe quel éditeur actuel. Les deux colonnes ci-dessous montrent ce que chacun des deux chargeurs de Java lirait à partir de ces mêmes octets.

Ce que lit chaque chargeur

Les deux chargeurs divergent. Le fichier est enregistré en UTF-8 et load(InputStream) lit un caractère par octet : tout ce qui dépasse l’ASCII arrive donc sous la forme de deux ou trois caractères au lieu d’un.

Cléload(InputStream), ISO 8859-1load(Reader), UTF-8
greetingdivergentcafécafé
farewelldivergentadiósadiós
ascii.onlythis line is fine either waythis line is fine either way

Les mêmes octets, décodés de deux façons. Les lignes signalées sont celles où les deux divergent : votre programme y verra une valeur différente selon la manière dont le fichier a été ouvert.

Bon à savoir

Rien à signaler.

La forme indépendante du chargeur

Tout ce qui dépasse l’ASCII écrit sous forme d’échappement, de sorte que les deux chargeurs lisent exactement la même chose. C’est ce que produit store(OutputStream), et la seule forme qu’un éditeur ne peut pas casser en changeant l’encodage du fichier.

Récapitulatif

Entrées
3
Clés sur lesquelles ils divergent
2

Tout fonctionne dans votre navigateur. Rien de ce que vous collez n’est envoyé ailleurs.

Aussi disponible en : English · Español · Português · العربية

Fichier .properties Java : accents, échappements et encodage

Collez un fichier .properties et comparez ce que chaque chargeur Java lit des mêmes octets, avec la forme échappée qui les met d’accord.

Qu’est-ce qu’un fichier .properties ?

Le fichier .properties est le format de configuration le plus ancien et le plus simple de Java : une clé et une valeur par ligne, séparées par un signe égal, et un croisillon pour les commentaires. Il figure dans la bibliothèque standard depuis l’origine, il reste le format de la plupart des paquets de traduction, et il est assez simple pour qu’on l’édite avec le logiciel qu’on a sous la main.

Cette simplicité cache quelque chose. Un fichier .properties n’a pas d’encodage propre. Rien dans le fichier n’indique lequel, il n’y a ni en-tête ni marque d’ordre des octets, et la réponse dépend entièrement de la méthode qui l’a ouvert. Lu par la méthode de flux, chaque octet devient un caractère, autrement dit de l’ISO 8859-1. Lu par la méthode de lecteur, c’est l’encodage avec lequel ce lecteur a été construit. Quant à la variante XML du même format, elle suppose UTF-8 par défaut. Un seul format, trois réponses.

Le fichier qui a l’air correct dans votre éditeur n’est donc pas forcément celui que lit votre programme. Cette page affiche les deux lectures des mêmes octets, signale les valeurs sur lesquelles elles divergent et fournit la forme échappée que les deux chargeurs lisent à l’identique.

Comment l’utiliser

  1. Collez le fichier. Il est encodé en UTF-8, ce qu’enregistre un éditeur actuel. Les boutons d’exemple couvrent du texte accentué, ce même texte déjà échappé, les règles de séparateurs et de commentaires, un chemin Windows et une ligne prolongée.
  2. Comparez les deux colonnes. L’une correspond à ce que lit le chargeur de flux, l’autre à ce que lit un lecteur UTF-8, à partir des mêmes octets. Une ligne signalée est une valeur que votre programme verra différemment selon la façon dont le fichier a été ouvert.
  3. Reprenez la forme échappée. Tout ce qui dépasse l’ASCII écrit sous forme d’échappement. Cette version ne casse pas quand un éditeur change l’encodage du fichier, et c’est ce qu’écrit Java lui-même lorsqu’il enregistre un .properties.

Pourquoi le même fichier se lit de deux façons

La documentation le dit sans détour : les méthodes de flux fonctionnent comme celles de lecteur, à ceci près que le flux est encodé en ISO 8859-1 et que chaque octet vaut un caractère Latin-1. L’implémentation est plus directe encore : un octet devient un caractère par masquage de ses huit bits de poids faible, sans le moindre décodeur.

Un fichier enregistré en UTF-8 puis lu par la méthode de flux donne donc un caractère par octet. Un e accent aigu occupe deux octets en UTF-8, et ces deux octets deviennent deux caractères : voilà pourquoi café arrive sous la forme café. La valeur ne se corrompt pas en chemin et rien ne prévient ; elle est simplement décodée selon une règle à laquelle celui qui a enregistré le fichier ne pensait pas.

Une distinction mérite ici d’être posée avec soin, car on la comprend facilement à l’envers. Une lettre latine accentuée est parfaitement représentable en ISO 8859-1 : le e accentué y tient sur un seul octet. Le problème n’est pas que le caractère soit impossible à écrire, c’est que le fichier a été écrit dans un encodage différent de celui avec lequel on le lit. Un caractère au-delà de U+00FF relève d’un autre cas : celui-là ne peut pas s’écrire en ISO 8859-1 du tout, et il faut l’échapper pour que le chargeur de flux le voie, quel que soit l’encodage du fichier.

L’échappement qui règle les deux cas s’écrit avec une barre oblique inverse, la lettre u et quatre chiffres hexadécimaux. Quatre exactement, et un seul u : la documentation le dit, et l’implémentation de référence lève une exception plutôt que de deviner si elle trouve autre chose. Le détail ne manque pas de sel, puisque le langage Java lui-même accepte n’importe quel nombre de u dans un échappement au sein du code source. Même syntaxe, deux règles, une seule plateforme.

Les règles d’échappement qui mangent vos données

Après une barre oblique inverse, quatre lettres seulement ont un sens : t, r, n et f, pour la tabulation, le retour chariot, le saut de ligne et le saut de page. Tout autre caractère qui la suit vaut pour lui-même, et la barre disparaît. C’est délibéré, puisque c’est ainsi qu’on place un deux-points ou un signe égal littéral dans une clé, mais cela transforme les chemins Windows en piège.

Écrivez un chemin sous la forme C, deux-points, barre oblique inverse, Users, barre oblique inverse, temp, et le résultat est pire que la perte des séparateurs. La première barre s’évanouit devant le U, et la seconde est suivie d’un t : elle devient donc une tabulation. Ce que reçoit votre programme, c’est C, deux-points, Users, une tabulation invisible, puis emp. Doubler chaque barre est la solution, et cela explique l’allure si étrange des fichiers .properties remplis de chemins Windows.

Les règles de ligne réservent leurs propres surprises. Une clé s’arrête au premier signe égal, deux-points, espace, tabulation ou saut de page, selon ce qui vient en premier : une ligne portant clé valeur, sans la moindre ponctuation, constitue donc une entrée parfaitement valide. Les espaces de début sont retirés de chaque ligne, le croisillon comme le point d’exclamation ouvrent un commentaire, et une ligne terminée par une barre oblique inverse se prolonge sur la suivante, dont les espaces de début sont eux aussi retirés. Cette dernière règle est ce qui permet de couper un long message et de l’indenter sans que l’indentation finisse dans la valeur.

Ce que cet outil ne fait pas

Il ne détermine pas ce que contient réellement votre fichier sur le disque. Vous saisissez ici du texte, et la page l’encode en UTF-8 parce que c’est ce qu’enregistrent les éditeurs d’aujourd’hui. Si votre fichier est bel et bien stocké en ISO 8859-1, alors c’est le chargeur de flux qui le lit correctement et c’est au lecteur qu’il faut le préciser : la même comparaison, dans l’autre sens.

Il s’arrête au format. Savoir si une valeur est une URL de base de données sensée, si une clé a sa place dans ce paquet, si le mécanisme des resource bundles trouvera seulement le fichier : rien de tout cela n’apparaît dans les octets ni n’est vérifié. Et si ce que vous avez est un texte déjà arrivé abîmé, l’outil de réparation de mojibake de ce site est la page qu’il vous faut ; celle-ci vise à produire un fichier qui ne puisse pas s’abîmer.

Le comportement décrit est celui de Java. D’autres langages lisent le même format avec leurs propres règles, et plusieurs supposent d’emblée UTF-8, ce qui explique précisément qu’un fichier fonctionne dans une chaîne d’outils et casse dans une autre. La forme échappée est le terrain commun : elle est en ASCII pur, si bien que tous les lecteurs s’accordent dessus.

Pourquoi est-ce gratuit ?

Encoder une chaîne et la relire de deux façons relève d’un calcul que votre navigateur effectue instantanément. Aucun serveur n’intervient : il n’y a donc rien à facturer ni de compte à créer.

Rien n’est envoyé. Le fichier que vous collez reste dans cet onglet.