J'essaye de lire les fichiers CSV en utilisant Java. Certains fichiers peuvent avoir une marque d'ordre d'octet au début, mais pas tous. Lorsqu'il est présent, l'ordre des octets est lu avec le reste de la première ligne, ce qui pose des problèmes avec les comparaisons de chaînes.
Existe-t-il un moyen simple de sauter la marque d'ordre des octets lorsqu'elle est présente?
Merci!
Réponses:
EDIT : J'ai fait une version appropriée sur GitHub: https://github.com/gpakosz/UnicodeBOMInputStream
Voici une classe que j'ai codée il y a quelque temps, je viens de modifier le nom du package avant de coller. Rien de spécial, c'est assez similaire aux solutions publiées dans la base de données de bogues de SUN. Incorporez-le dans votre code et tout va bien.
Et vous l'utilisez de cette façon:
la source
La bibliothèque Apache Commons IO a un
InputStream
qui peut détecter et supprimer les nomenclatures:BOMInputStream
(javadoc) :Si vous avez également besoin de détecter différents encodages, il peut également faire la distinction entre différentes marques d'ordre d'octet, par exemple UTF-8 vs UTF-16 big + little endian - détails sur le lien doc ci-dessus. Vous pouvez ensuite utiliser le détecté
ByteOrderMark
pour choisir unCharset
pour décoder le flux. (Il existe probablement un moyen plus simple de le faire si vous avez besoin de toutes ces fonctionnalités - peut-être l'UnicodeReader dans la réponse de BalusC?). Notez qu'en général, il n'y a pas un très bon moyen de détecter le codage de certains octets, mais si le flux commence par une nomenclature, cela peut apparemment être utile.Edit : Si vous devez détecter la nomenclature en UTF-16, UTF-32, etc., le constructeur doit être:
Upvote @ le commentaire de martin-charlesworth :)
la source
boolean
argument pour spécifier s'il faut inclure ou exclure la nomenclature. Exemple:BOMInputStream bomIn = new BOMInputStream(in, false); // don't include the BOM
BOMInputStream bomIn = new BOMInputStream(is, ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_32BE, ByteOrderMark.UTF_32LE);
BOMInputStream(InputStream delegate) Constructs a new BOM InputStream that excludes a ByteOrderMark.UTF_8 BOM.
Solution plus simple:
Échantillon d'utilisation:
Cela fonctionne avec les 5 encodages UTF!
la source
L'API Google Data a un
UnicodeReader
qui détecte automatiquement l'encodage.Vous pouvez l'utiliser à la place de
InputStreamReader
. Voici un extrait -légèrement compacté- de sa source qui est assez simple:la source
(bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)
être vrai, le cas UTF-16LE ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)
) aurait déjà correspondu.Le BOMInputStream de
Apache Commons IO
la bibliothèque a déjà été mentionné par @rescdsk, mais je ne l'ai pas vu mentionner comment obtenir unInputStream
sans la nomenclature.Voici comment je l'ai fait dans Scala.
la source
public BOMInputStream(InputStream delegate) { this(delegate, false, ByteOrderMark.UTF_8); }
. Il exclutUTF-8 BOM
par défaut.Constructs a new BOM InputStream that excludes a ByteOrderMark.UTF_8 BOM.
Pour supprimer simplement les caractères de nomenclature de votre fichier, je recommande d'utiliser Apache Common IO
Définissez include sur false et vos caractères de nomenclature seront exclus.
la source
Malheureusement non. Vous devrez vous identifier et vous ignorer. Cette page détaille ce que vous devez surveiller. Voir également cette question SO pour plus de détails.
la source
J'ai eu le même problème, et parce que je ne lisais pas un tas de fichiers, j'ai fait une solution plus simple. Je pense que mon encodage était UTF-8 parce que lorsque j'ai imprimé le caractère incriminé à l'aide de cette page: Obtenez la valeur unicode d'un caractère, j'ai trouvé que c'était le cas
\ufeff
. J'ai utilisé le codeSystem.out.println( "\\u" + Integer.toHexString(str.charAt(0) | 0x10000).substring(1) );
pour imprimer la valeur unicode incriminée.Une fois que j'ai eu la valeur unicode incriminée, je l'ai remplacée dans la première ligne de mon fichier avant de continuer la lecture. La logique métier de cette section:
Cela a résolu mon problème. Ensuite, j'ai pu continuer à traiter le fichier sans problème. J'ai ajouté
trim()
juste en cas d'espaces blancs de début ou de fin, vous pouvez le faire ou non, en fonction de vos besoins spécifiques.la source