Próbuję odczytać pliki CSV przy użyciu języka Java. Niektóre pliki mogą mieć znacznik kolejności bajtów na początku, ale nie wszystkie. Gdy występuje, kolejność bajtów jest odczytywana wraz z resztą pierwszego wiersza, powodując w ten sposób problemy z porównaniami łańcuchów.
Czy istnieje łatwy sposób na pominięcie znaku kolejności bajtów, gdy jest obecny?
Dzięki!
java
utf-8
byte-order-mark
Tomek
źródło
źródło
Odpowiedzi:
EDYCJA : zrobiłem poprawne wydanie na GitHub: https://github.com/gpakosz/UnicodeBOMInputStream
Oto klasa, którą kodowałem jakiś czas temu, właśnie zmieniłem nazwę pakietu przed wklejeniem. Nic specjalnego, jest dość podobny do rozwiązań opublikowanych w bazie błędów SUN. Włącz to do swojego kodu i wszystko w porządku.
I używasz tego w ten sposób:
źródło
Biblioteka Apache Commons IO ma funkcję
InputStream
wykrywania i odrzucania zestawień komponentów:BOMInputStream
(javadoc) :Jeśli potrzebujesz również wykryć różne kodowania, może również rozróżnić różne znaczniki kolejności bajtów, np. UTF-8 kontra UTF-16 duży + mały endian - szczegóły w linku do dokumentu powyżej. Następnie możesz użyć wykrytego,
ByteOrderMark
aby wybraćCharset
do dekodowania strumienia. (Prawdopodobnie istnieje bardziej usprawniony sposób, aby to zrobić, jeśli potrzebujesz całej tej funkcjonalności - może UnicodeReader w odpowiedzi BalusC?). Zwróć uwagę, że ogólnie rzecz biorąc, nie ma dobrego sposobu na wykrycie kodowania niektórych bajtów, ale jeśli strumień zaczyna się od BOM, najwyraźniej może to być pomocne.Edycja : Jeśli chcesz wykryć BOM w UTF-16, UTF-32 itp., Konstruktor powinien być:
Głosuj za komentarzem @ martin-charlesworth :)
źródło
boolean
argument dotyczący określenia, czy należy uwzględnić, czy wykluczyć zestawienie komponentów. Przykład: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.
Bardziej proste rozwiązanie:
Próbka użycia:
Działa ze wszystkimi 5 kodowaniami UTF!
źródło
Google Data API ma,
UnicodeReader
który automagicznie wykrywa kodowanie.Możesz go użyć zamiast
InputStreamReader
. Oto - lekko zagęszczony - wyciąg z jego źródła, który jest dość prosty:źródło
(bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)
była prawdziwa, przypadek UTF-16LE ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)
) już by się dopasował.The
Apache Commons IO
Biblioteki BOMInputStream już wspomniano przez @rescdsk, ale nie widzę go wymienić jak uzyskaćInputStream
bez BOM.Oto, jak zrobiłem to w Scali.
źródło
public BOMInputStream(InputStream delegate) { this(delegate, false, ByteOrderMark.UTF_8); }
.UTF-8 BOM
Domyślnie wyklucza .Constructs a new BOM InputStream that excludes a ByteOrderMark.UTF_8 BOM.
Aby po prostu usunąć znaki BOM z pliku, zalecam użycie Apache Common IO
Ustaw włącz na false, a znaki zestawienia komponentów zostaną wykluczone.
źródło
Niestety nie. Będziesz musiał zidentyfikować się i pominąć siebie. Ta strona zawiera szczegółowe informacje na temat tego, na co musisz uważać. Zobacz również to pytanie SO, aby uzyskać więcej informacji.
źródło
Miałem ten sam problem, a ponieważ nie czytałem w kilku plikach, zastosowałem prostsze rozwiązanie. Myślę, że moje kodowanie to UTF-8, ponieważ kiedy wydrukowałem obraźliwy znak za pomocą tej strony: Uzyskaj wartość Unicode znaku , stwierdziłem, że to był
\ufeff
. Użyłem koduSystem.out.println( "\\u" + Integer.toHexString(str.charAt(0) | 0x10000).substring(1) );
do wydrukowania niewłaściwej wartości Unicode.Kiedy już miałem obraźliwą wartość Unicode, zastąpiłem ją w pierwszym wierszu mojego pliku, zanim zacząłem czytać. Logika biznesowa tej sekcji:
To rozwiązało mój problem. Wtedy mogłem kontynuować przetwarzanie pliku bez problemu. Dodałem
trim()
tylko w przypadku wiodących lub końcowych białych znaków, możesz to zrobić lub nie, w zależności od twoich konkretnych potrzeb.źródło