Je lis un fichier via un FileReader - le fichier est décodé UTF-8 (avec BOM) maintenant mon problème est: j'ai lu le fichier et sorti une chaîne, mais malheureusement le marqueur BOM est également sorti. Pourquoi cela se produit-il?
fr = new FileReader(file);
br = new BufferedReader(fr);
String tmp = null;
while ((tmp = br.readLine()) != null) {
String text;
text = new String(tmp.getBytes(), "UTF-8");
content += text + System.getProperty("line.separator");
}
sortie après la première ligne
?<style>
En Java, vous devez consommer manuellement la nomenclature UTF8 si elle est présente. Ce comportement est documenté dans la base de données Java, ici et ici . Il n'y aura pas de correctif pour l'instant car il cassera les outils existants comme les analyseurs JavaDoc ou XML. Le Apache IO Commons fournit un BOMInputStream
pour gérer cette situation.
Jetez un œil à cette solution: Gérer le fichier UTF8 avec la nomenclature
La solution la plus simple consiste probablement à supprimer le \uFEFF
à partir de la chaîne, car il est extrêmement peu probable qu'elle apparaisse pour une autre raison.
tmp = tmp.replace("\uFEFF", "");
Voir aussi ce rapport de bug sur la goyave
Utilisez la bibliothèque Apache Commons .
Classe: org.Apache.commons.io.input.BOMInputStream
Exemple d'utilisation:
String defaultEncoding = "UTF-8";
InputStream inputStream = new FileInputStream(someFileWithPossibleUtf8Bom);
try {
BOMInputStream bOMInputStream = new BOMInputStream(inputStream);
ByteOrderMark bom = bOMInputStream.getBOM();
String charsetName = bom == null ? defaultEncoding : bom.getCharsetName();
InputStreamReader reader = new InputStreamReader(new BufferedInputStream(bOMInputStream), charsetName);
//use reader
} finally {
inputStream.close();
}
Voici comment j'utilise Apache BOMInputStream, il utilise un bloc try-with-resources. L'argument "false" indique à l'objet d'ignorer les nomenclatures suivantes (nous utilisons des fichiers texte "sans nomenclature" pour des raisons de sécurité, haha):
try( BufferedReader br = new BufferedReader(
new InputStreamReader( new BOMInputStream( new FileInputStream(
file), false, ByteOrderMark.UTF_8,
ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE,
ByteOrderMark.UTF_32BE, ByteOrderMark.UTF_32LE ) ) ) )
{
// use br here
} catch( Exception e)
}
Utilisez Apache Commons IO .
Par exemple, jetons un œil à mon code (utilisé pour lire un fichier texte avec des caractères latins et cyrilliques) ci-dessous:
String defaultEncoding = "UTF-16";
InputStream inputStream = new FileInputStream(new File("/temp/1.txt"));
BOMInputStream bomInputStream = new BOMInputStream(inputStream);
ByteOrderMark bom = bomInputStream.getBOM();
String charsetName = bom == null ? defaultEncoding : bom.getCharsetName();
InputStreamReader reader = new InputStreamReader(new BufferedInputStream(bomInputStream), charsetName);
int data = reader.read();
while (data != -1) {
char theChar = (char) data;
data = reader.read();
ari.add(Character.toString(theChar));
}
reader.close();
Par conséquent, nous avons une ArrayList nommée "ari" avec tous les caractères du fichier "1.txt" à l'exception de la nomenclature.
Considérez nicodeReader de Google qui fait tout ce travail pour vous.
Charset utf8 = Charset.forName("UTF-8"); // default if no BOM present
try (Reader r = new UnicodeReader(new FileInputStream(file), utf8)) {
....
}
Dépendance Maven:
<dependency>
<groupId>com.google.gdata</groupId>
<artifactId>core</artifactId>
<version>1.47.1</version>
</dependency>
Il est mentionné ici qu'il s'agit généralement d'un problème avec les fichiers sous Windows.
Une solution possible serait d'exécuter le fichier via un outil comme dos2unix en premier.
Le moyen le plus simple que j'ai trouvé pour contourner la nomenclature
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
while ((currentLine = br.readLine()) != null) {
//case of, remove the BOM of UTF-8 BOM
currentLine = currentLine.replace("","");
Si quelqu'un veut le faire avec la norme, ce serait un moyen:
public static String cutBOM(String value) {
// UTF-8 BOM is EF BB BF, see https://en.wikipedia.org/wiki/Byte_order_mark
String bom = String.format("%x", new BigInteger(1, value.substring(0,3).getBytes()));
if (bom.equals("efbbbf"))
// UTF-8
return value.substring(3, value.length());
else if (bom.substring(0, 2).equals("feff") || bom.substring(0, 2).equals("ffe"))
// UTF-16BE or UTF16-LE
return value.substring(2, value.length());
else
return value;
}