Il y a plusieurs facteurs à l'œuvre:
- Les fichiers texte n'ont pas de métadonnées intrinsèques pour décrire leur encodage (pour toutes les discussions sur les taxes en tranches d'angle, il y a des raisons XML est populaire)
- L'encodage par défaut pour Windows est toujours un 8bit (ou double octet) caractère « ANSI » set avec une gamme limitée de valeurs - fichiers texte écrit dans ce format ne sont pas portables
- Pour dire un fichier Unicode à partir d'un Fichier ANSI, les applications Windows s'appuient sur la présence d'un byte order mark au début du fichier (not strictly true - Raymond Chen explains). En théorie, la nomenclature est là pour vous indiquer le endianess (ordre des octets) des données. Pour UTF-8, même s'il n'y a qu'un seul ordre d'octets, les applications Windows s'appuient sur les octets de marqueur pour déterminer automatiquement qu'il s'agit d'Unicode (bien que vous remarquiez que le Bloc-notes dispose d'une option d'encodage).
- Il est faux de dire que Java est cassé parce qu'il n'écrit pas automatiquement une nomenclature UTF-8. Sur les systèmes Unix, ce serait une erreur d'écrire une nomenclature dans un fichier script, par exemple, et de nombreux systèmes Unix utilisent UTF-8 comme encodage par défaut. Il y a des moments où vous ne voulez pas sous Windows, que ce soit, comme lorsque vous l'ajout de données à un fichier existant:
fos = new FileOutputStream(FileName,Append);
Voici une méthode de annexant fiable des données UTF-8 dans un fichier:
private static void writeUtf8ToFile(File file, boolean append, String data)
throws IOException {
boolean skipBOM = append && file.isFile() && (file.length() > 0);
Closer res = new Closer();
try {
OutputStream out = res.using(new FileOutputStream(file, append));
Writer writer = res.using(new OutputStreamWriter(out, Charset
.forName("UTF-8")));
if (!skipBOM) {
writer.write('\uFEFF');
}
writer.write(data);
} finally {
res.close();
}
}
Utilisation:
public static void main(String[] args) throws IOException {
String chinese = "\u4E0A\u6D77";
boolean append = true;
writeUtf8ToFile(new File("chinese.txt"), append, chinese);
}
note: si le fichier existait déjà et que vous avez choisi d'ajouter les données existantes et n'a pas été UTF-8 codé, la seule chose que le code w mal créer est un gâchis.
Voici le type Closer
utilisé dans ce code:
public class Closer implements Closeable {
private Closeable closeable;
public <T extends Closeable> T using(T t) {
closeable = t;
return t;
}
@Override public void close() throws IOException {
if (closeable != null) {
closeable.close();
}
}
}
Ce code fait une meilleure estimation de style de Windows sur la façon de lire le fichier en fonction des marques d'ordre d'octet:
private static final Charset[] UTF_ENCODINGS = { Charset.forName("UTF-8"),
Charset.forName("UTF-16LE"), Charset.forName("UTF-16BE") };
private static Charset getEncoding(InputStream in) throws IOException {
charsetLoop: for (Charset encodings : UTF_ENCODINGS) {
byte[] bom = "\uFEFF".getBytes(encodings);
in.mark(bom.length);
for (byte b : bom) {
if ((0xFF & b) != in.read()) {
in.reset();
continue charsetLoop;
}
}
return encodings;
}
return Charset.defaultCharset();
}
private static String readText(File file) throws IOException {
Closer res = new Closer();
try {
InputStream in = res.using(new FileInputStream(file));
InputStream bin = res.using(new BufferedInputStream(in));
Reader reader = res.using(new InputStreamReader(bin, getEncoding(bin)));
StringBuilder out = new StringBuilder();
for (int ch = reader.read(); ch != -1; ch = reader.read())
out.append((char) ch);
return out.toString();
} finally {
res.close();
}
}
Utilisation :
public static void main(String[] args) throws IOException {
System.out.println(readText(new File("chinese.txt")));
}
(System.out utilise l'encodage par défaut, donc si elle imprime quoi que ce soit Sensi ble dépend de votre plate-forme et configuration.)
duplication possible de [Qu'est-ce que le codage de caractères et pourquoi devrais-je m'en préoccuper?] (http://stackoverflow.com/questions/10611455/what-is-character-encoding-and -why-should-i-bother-with-it) – Raedwald