Maison > Java > javaDidacticiel > Comment gérer les marques d'ordre d'octet (BOM) lors de la lecture de fichiers CSV en Java ?

Comment gérer les marques d'ordre d'octet (BOM) lors de la lecture de fichiers CSV en Java ?

Patricia Arquette
Libérer: 2024-12-27 09:57:10
original
978 Les gens l'ont consulté

How to Handle Byte Order Marks (BOMs) When Reading CSV Files in Java?

La marque d'ordre des octets provoque des problèmes de lecture des fichiers CSV en Java

La marque d'ordre des octets (BOM) peut être présente au début de certains fichiers CSV fichiers, mais pas du tout. Lorsqu'elle est présente, la nomenclature est lue avec la première ligne du fichier, ce qui provoque des problèmes lors de la comparaison des chaînes.

Voici comment résoudre ce problème :

Solution :

Implémentez une classe wrapper, UnicodeBOMInputStream, qui détecte la présence d'une nomenclature Unicode au début d'un flux d'entrée. Si une nomenclature est détectée, la méthode skipBOM() peut être utilisée pour la supprimer.

Voici un exemple de la classe UnicodeBOMInputStream :

import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;

public class UnicodeBOMInputStream extends InputStream {

    private PushbackInputStream in;
    private BOM bom;
    private boolean skipped = false;

    public UnicodeBOMInputStream(InputStream inputStream) throws IOException {
        if (inputStream == null)
            throw new NullPointerException("Invalid input stream: null is not allowed");

        in = new PushbackInputStream(inputStream, 4);

        byte[] bom = new byte[4];
        int read = in.read(bom);

        switch (read) {
            case 4:
                if ((bom[0] == (byte) 0xFF) &&
                        (bom[1] == (byte) 0xFE) &&
                        (bom[2] == (byte) 0x00) &&
                        (bom[3] == (byte) 0x00)) {
                    this.bom = BOM.UTF_32_LE;
                    break;
                } else if ((bom[0] == (byte) 0x00) &&
                        (bom[1] == (byte) 0x00) &&
                        (bom[2] == (byte) 0xFE) &&
                        (bom[3] == (byte) 0xFF)) {
                    this.bom = BOM.UTF_32_BE;
                    break;
                }
            case 3:
                if ((bom[0] == (byte) 0xEF) &&
                        (bom[1] == (byte) 0xBB) &&
                        (bom[2] == (byte) 0xBF)) {
                    this.bom = BOM.UTF_8;
                    break;
                }
            case 2:
                if ((bom[0] == (byte) 0xFF) &&
                        (bom[1] == (byte) 0xFE)) {
                    this.bom = BOM.UTF_16_LE;
                    break;
                } else if ((bom[0] == (byte) 0xFE) &&
                        (bom[1] == (byte) 0xFF)) {
                    this.bom = BOM.UTF_16_BE;
                    break;
                }
            default:
                this.bom = BOM.NONE;
                break;
        }

        if (read > 0)
            in.unread(bom, 0, read);
    }

    public BOM getBOM() {
        return bom;
    }

    public UnicodeBOMInputStream skipBOM() throws IOException {
        if (!skipped) {
            in.skip(bom.bytes.length);
            skipped = true;
        }
        return this;
    }

    @Override
    public int read() throws IOException {
        return in.read();
    }

    @Override
    public int read(byte[] b) throws IOException {
        return in.read(b, 0, b.length);
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        return in.read(b, off, len);
    }

    @Override
    public long skip(long n) throws IOException {
        return in.skip(n);
    }

    @Override
    public int available() throws IOException {
        return in.available();
    }

    @Override
    public void close() throws IOException {
        in.close();
    }

    @Override
    public synchronized void mark(int readlimit) {
        in.mark(readlimit);
    }

    @Override
    public synchronized void reset() throws IOException {
        in.reset();
    }

    @Override
    public boolean markSupported() {
        return in.markSupported();
    }

    private enum BOM {
        NONE, UTF_8, UTF_16_LE, UTF_16_BE, UTF_32_LE, UTF_32_BE
    }
}
Copier après la connexion

Utilisation :

Utilisez le wrapper UnicodeBOMInputStream comme suit :

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;

public class CSVReaderWithBOM {

    public static void main(String[] args) throws Exception {
        FileInputStream fis = new FileInputStream("test.csv");
        UnicodeBOMInputStream ubis = new UnicodeBOMInputStream(fis);

        System.out.println("Detected BOM: " + ubis.getBOM());

        System.out.print("Reading the content of the file without skipping the BOM: ");
        InputStreamReader isr = new InputStreamReader(ubis);
        BufferedReader br = new BufferedReader(isr);

        System.out.println(br.readLine());

        br.close();
        isr.close();
        ubis.close();
        fis.close();

        fis = new FileInputStream("test.csv");
        ubis = new UnicodeBOMInputStream(fis);
        isr = new InputStreamReader(ubis);
        br = new BufferedReader(isr);

        ubis.skipBOM();

        System.out.print("Reading the content of the file after skipping the BOM: ");
        System.out.println(br.readLine());

        br.close();
        isr.close();
        ubis.close();
        fis.close();
    }
}
Copier après la connexion

Cette approche vous permet de lire des fichiers CSV avec ou sans nomenclature et d'éviter les problèmes de comparaison de chaînes causés par la présence de la nomenclature dans la première ligne du fichier.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal