web-dev-qa-db-fra.com

Écrire un fichier en UTF-8 en utilisant FileWriter (Java)?

J'ai le code suivant cependant, je veux qu'il écrive comme un fichier UTF-8 pour gérer les caractères étrangers. Y a-t-il un moyen de faire cela, est-il nécessaire d'avoir un paramètre?

J'apprécierais vraiment votre aide avec ceci. Merci.

try {
  BufferedReader reader = new BufferedReader(new FileReader("C:/Users/Jess/My Documents/actresses.list"));
  writer = new BufferedWriter(new FileWriter("C:/Users/Jess/My Documents/actressesFormatted.csv"));
  while( (line = reader.readLine()) != null) {
    //If the line starts with a tab then we just want to add a movie
    //using the current actor's name.
    if(line.length() == 0)
      continue;
    else if(line.charAt(0) == '\t') {
      readMovieLine2(0, line, surname.toString(), forename.toString());
    } //Else we've reached a new actor
    else {
      readActorName(line);
    }
  }
} catch (IOException e) {
  e.printStackTrace();
}
72
user1280970

Constructeurs de codage sûr

Obtenir Java pour vous avertir correctement des erreurs de codage est délicat. Vous devez utiliser le le plus détaillé et, hélas, le le moins utilisé des quatre autres constructeurs pour chacun de InputStreamReader et OutputStreamWriter de recevoir une exception appropriée sur un problème d'encodage.

Pour les entrées/sorties de fichiers, veillez à toujours utiliser comme second argument les arguments OutputStreamWriter et InputStreamReader du codeur fantaisie:

  Charset.forName("UTF-8").newEncoder()

Il existe d'autres possibilités encore plus sophistiquées, mais aucune des trois possibilités plus simples ne fonctionne pour la gestion des exceptions. Ceux-ci font:

 OutputStreamWriter char_output = new OutputStreamWriter(
     new FileOutputStream("some_output.utf8"),
     Charset.forName("UTF-8").newEncoder() 
 );

 InputStreamReader char_input = new InputStreamReader(
     new FileInputStream("some_input.utf8"),
     Charset.forName("UTF-8").newDecoder() 
 );

Quant à courir avec

 $ Java -Dfile.encoding=utf8 SomeTrulyRemarkablyLongcLassNameGoeShere

Le problème est que cela n'utilisera pas la forme complète de l'argument du codeur pour les flux de caractères, ce qui vous évitera de nouveau des problèmes de codage.

Exemple plus long

Voici un exemple plus long, celui-ci gérant un processus au lieu d’un fichier, où nous promouvons deux flux d’octets d’entrée différents et un flux d’octets de sortie, le tout en flux de caractères UTF-8 avec gestion complète des exceptions :

 // this runs a Perl script with UTF-8 STD{IN,OUT,ERR} streams
 Process
 slave_process = Runtime.getRuntime().exec("Perl -CS script args");

 // fetch his stdin byte stream...
 OutputStream
 __bytes_into_his_stdin  = slave_process.getOutputStream();

 // and make a character stream with exceptions on encoding errors
 OutputStreamWriter
   chars_into_his_stdin  = new OutputStreamWriter(
                             __bytes_into_his_stdin,
         /* DO NOT OMIT! */  Charset.forName("UTF-8").newEncoder()
                         );

 // fetch his stdout byte stream...
 InputStream
 __bytes_from_his_stdout = slave_process.getInputStream();

 // and make a character stream with exceptions on encoding errors
 InputStreamReader
   chars_from_his_stdout = new InputStreamReader(
                             __bytes_from_his_stdout,
         /* DO NOT OMIT! */  Charset.forName("UTF-8").newDecoder()
                         );

// fetch his stderr byte stream...
 InputStream
 __bytes_from_his_stderr = slave_process.getErrorStream();

 // and make a character stream with exceptions on encoding errors
 InputStreamReader
   chars_from_his_stderr = new InputStreamReader(
                             __bytes_from_his_stderr,
         /* DO NOT OMIT! */  Charset.forName("UTF-8").newDecoder()
                         );

Maintenant, vous avez trois flux de caractères qui déclenchent tous une exception sur les erreurs de codage, respectivement appelés chars_into_his_stdin, chars_from_his_stdout, et chars_from_his_stderr.

Ceci n’est que légèrement plus compliqué que ce dont vous avez besoin pour votre problème, la solution que j’ai donnée dans la première moitié de cette réponse. Le point clé est que c’est le seul moyen de détecter les erreurs de codage.

Ne faites pas que je commence par parler de PrintStreams manger des exceptions.

70
tchrist

Ditch FileWriter et FileReader, inutiles car ils ne vous permettent pas de spécifier l'encodage. Au lieu de cela, utilisez

new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)

et

new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);

48
Michael Borgwardt

Vous devez utiliser la classe OutputStreamWriter comme paramètre d'écriture pour votre BufferedWriter. Il accepte un encodage. Passez en revue javadocs pour cela.

Un peu comme ça:

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
    new FileOutputStream("jedis.txt"), "UTF-8"
));

Ou vous pouvez définir le codage du système actuel avec la propriété système file.encoding Sur UTF-8.

Java -Dfile.encoding=UTF-8 com.jediacademy.Runner arg1 arg2 ...

Vous pouvez également le définir en tant que propriété système au moment de l'exécution avec System.setProperty(...) si vous n'en avez besoin que pour ce fichier spécifique, mais dans un cas comme celui-ci, je préférerais le OutputStreamWriter.

En définissant la propriété système, vous pouvez utiliser FileWriter et vous attendre à ce qu'il utilise UTF-8 comme codage par défaut pour vos fichiers. Dans ce cas, pour tous les fichiers que vous lisez et écrivez.

[~ # ~] éditer [~ # ~]

  • À partir de l'API 19, vous pouvez remplacer la chaîne "UTF-8" par StandardCharsets.UTF_8

  • Comme suggéré dans les commentaires ci-dessous par tchrist , si vous avez l'intention de détecter les erreurs d'encodage dans votre fichier, vous serez forcé d'utiliser l'approche OutputStreamWriter et d'utiliser le constructeur qui reçoit un encodeur de jeu de caractères.

    Un peu comme

    CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
    encoder.onMalformedInput(CodingErrorAction.REPORT);
    encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("jedis.txt"),encoder));
    

    Vous pouvez choisir entre les actions IGNORE | REPLACE | REPORT

En outre, cette question a déjà été répondue ici .

43
Edwin Dalorzo

Avec le texte chinois, j'ai essayé d'utiliser le Charset UTF-16 et, heureusement, ça marche.

J'espère que cela pourrait aider!

PrintWriter out = new PrintWriter( file, "UTF-16" );
5
Phuong

Depuis Java 7, il existe un moyen simple de gérer le codage de caractères de BufferedWriter et BufferedReaders. Vous pouvez créer un BufferedWriter directement à l'aide de la classe Files au lieu de créer différentes instances de Writer. Vous pouvez simplement créer un BufferedWriter, qui considère le codage de caractères, en appelant:

Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8);

Vous pouvez en savoir plus sur JavaDoc:

3
Lars Briem

Depuis Java 11, vous pouvez faire:

FileWriter fw = new FileWriter("filename.txt", Charset.forName("utf-8"));
3
mortensi