web-dev-qa-db-fra.com

Utilisation de l'encodage par défaut, que dois-je utiliser et pourquoi?

FindBugs rapporte un bug: 

Utilisation du codage par défaut Nous avons trouvé un appel à une méthode qui effectuera une conversion d'octet en chaîne (ou de chaîne en octets) et supposera que le codage par défaut de la plate-forme convient. Cela entraînera une modification du comportement de l'application entre les plates-formes. Utilisez une autre API et spécifiez explicitement un nom de jeu de caractères ou un objet Charset.

J'ai utilisé FileReader comme ceci (juste un morceau de code):

public ArrayList<String> getValuesFromFile(File file){
    String line;
    StringTokenizer token;
    ArrayList<String> list = null;
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader(file));
        list = new ArrayList<String>();
        while ((line = br.readLine())!=null){
            token = new StringTokenizer(line);
            token.nextToken();
            list.add(token.nextToken());
    ...

Pour corriger le bug je dois changer 

br = new BufferedReader(new FileReader(file));

à 

br = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.defaultCharset()));

Et quand j'utilise PrintWriter, la même erreur s'est produite. Alors maintenant, j'ai une question. Quand je peux (devrais) utiliser FileReader et PrintWriter, s’il ne s’agit pas d’une bonne pratique, s’appuyer sur le codage par défaut? J'ai décidé d'utiliser cette méthode pour définir automatiquement le jeu de caractères du système d'exploitation de l'utilisateur. 

19
Nikolas

Si le fichier est sous le contrôle de votre application et si vous souhaitez que le fichier soit codé dans le codage par défaut de la plate-forme, vous pouvez utiliser le codage par défaut de la plate-forme. En le spécifiant explicitement, il est plus clair pour vous et les futurs responsables que cela est votre intention. Ce serait un défaut raisonnable pour un éditeur de texte, par exemple, qui écrirait ensuite des fichiers que tout autre éditeur de cette plate-forme serait alors en mesure de lire.

Si, par contre, vous voulez vous assurer que tous les caractères possibles peuvent être écrits dans votre fichier, vous devez utiliser un codage universel comme UTF8.

Et si le fichier provient d'une application externe ou est censé être compatible avec une application externe, vous devez utiliser le codage attendu par cette application externe.

Ce que vous devez comprendre, c’est que si vous écrivez un fichier comme sur une machine et le lisez comme vous le faites sur une autre machine, qui n’a pas le même encodage par défaut, vous ne pourrez pas forcément lisez ce que vous avez écrit. Utiliser un codage spécifique pour écrire et lire, comme UTF8, garantit que le fichier sera toujours le même, quelle que soit la plate-forme utilisée lors de l'écriture du fichier.

21
JB Nizet

Idéalement, il devrait être:

try (InputStream in = new FileInputStream(file);
     Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
     BufferedReader br = new BufferedReader(reader)) {

...ou:

try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {

... en supposant que le fichier est codé au format UTF-8.

Presque tous les encodages qui ne sont pas un format de transformation Unicode sont obsolètes pour les données en langage naturel. Il existe des langues que vous ne pouvez pas prendre en charge sans Unicode.

20
McDowell

Vous devez utiliser le codage par défaut chaque fois que vous lisez un fichier ne se trouvant pas dans votre application et pouvant être considéré comme appartenant au codage local de l'utilisateur, par exemple des fichiers texte écrits par l'utilisateur. Vous voudrez peut-être utiliser le codage par défaut lors de l'écriture de tels fichiers, en fonction de ce que l'utilisateur fera ultérieurement avec ce fichier.

Vous devriez pas utiliser le codage par défaut pour tout autre fichier, en particulier les fichiers pertinents pour l’application.

Si votre application écrit par exemple des fichiers de configuration au format texte, vous devez toujours spécifier le codage. En général, UTF-8 est toujours un bon choix, car il est compatible avec presque tout. Ne pas le faire pourrait provoquer des accidents inattendus d'utilisateurs dans d'autres pays.

Cela ne se limite pas au codage de caractères, mais également aux formats de date/heure, numériques ou autres langues. Si, par exemple, vous utilisez le codage par défaut et les chaînes de date/heure par défaut sur une machine américaine, essayez de lire ce fichier sur un serveur allemand. Vous serez peut-être surpris de savoir pourquoi une moitié est du charabia et l'autre moitié avec mois/jours confus ou désactivée d'une heure à cause de l'heure d'été.

3
TwoThe

Lorsque vous utilisez un PrintWriter,

File file = new File(file_path);
Writer w = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_16.name());
PrintWriter pw = new PrintWriter(w);
pw.println(content_to_write);
pw.close();
0
prime