Saya mencoba membaca file CSV menggunakan Java. Beberapa file mungkin memiliki tanda urutan byte di awal, tetapi tidak semua. Saat ini, urutan byte dibaca bersama dengan baris pertama lainnya, sehingga menyebabkan masalah dengan perbandingan string.
Apakah ada cara mudah untuk melewati tanda urutan byte jika ada?
Terima kasih!
Jawaban:
EDIT : Saya telah membuat rilis yang tepat di GitHub: https://github.com/gpakosz/UnicodeBOMInputStream
Ini adalah kelas yang saya kodekan beberapa waktu lalu, saya baru saja mengedit nama paket sebelum menempel. Tidak ada yang istimewa, ini sangat mirip dengan solusi yang diposting di database bug SUN. Gabungkan dalam kode Anda dan Anda baik-baik saja.
Dan Anda menggunakannya dengan cara ini:
sumber
The Apache Commons IO perpustakaan memiliki
InputStream
yang dapat mendeteksi dan membuang BOMs:BOMInputStream
(javadoc) :Jika Anda juga perlu mendeteksi pengkodean yang berbeda, itu juga dapat membedakan di antara berbagai tanda urutan byte yang berbeda, misalnya UTF-8 vs. UTF-16 big + little endian - detailnya ada di tautan dokumen di atas. Anda kemudian dapat menggunakan file yang terdeteksi
ByteOrderMark
untuk memilihCharset
untuk memecahkan kode aliran. (Mungkin ada cara yang lebih efisien untuk melakukan ini jika Anda membutuhkan semua fungsi ini - mungkin UnicodeReader dalam jawaban BalusC?). Perhatikan bahwa, secara umum, tidak ada cara yang baik untuk mendeteksi pengkodean beberapa byte, tetapi jika streaming dimulai dengan BOM, tampaknya ini bisa membantu.Edit : Jika Anda perlu mendeteksi BOM dalam UTF-16, UTF-32, dll, maka konstruktornya harus:
Suka komentar @ martin-charlesworth :)
sumber
boolean
argumen untuk menentukan apakah akan menyertakan atau mengecualikan BOM. Contoh: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.
Solusi yang lebih sederhana:
Contoh penggunaan:
Ia bekerja dengan semua 5 pengkodean UTF!
sumber
Google Data API memiliki
UnicodeReader
yang secara otomatis mendeteksi pengkodean.Anda dapat menggunakannya sebagai pengganti
InputStreamReader
. Berikut adalah ekstrak -sedikit kompak- dari sumbernya yang cukup mudah:sumber
(bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)
menjadi benar, maka UTF-16LE case ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)
) akan sudah cocok.The
Apache Commons IO
Perpustakaan BOMInputStream telah disebutkan oleh @rescdsk, tapi saya tidak melihatnya lagi bagaimana untuk mendapatkanInputStream
tanpa BOM tersebut.Inilah cara saya melakukannya di Scala.
sumber
public BOMInputStream(InputStream delegate) { this(delegate, false, ByteOrderMark.UTF_8); }
. Ini tidak termasukUTF-8 BOM
secara default.Constructs a new BOM InputStream that excludes a ByteOrderMark.UTF_8 BOM.
Untuk hanya menghapus karakter BOM dari file Anda, saya merekomendasikan menggunakan Apache Common IO
Setel sertakan ke salah dan karakter BOM Anda akan dikecualikan.
sumber
Sayangnya tidak. Anda harus mengidentifikasi dan melewatkan diri Anda sendiri.Halaman ini merinci apa yang harus Anda perhatikan. Lihat juga pertanyaan SO ini untuk lebih jelasnya.
sumber
Saya memiliki masalah yang sama, dan karena saya tidak membaca banyak file, saya melakukan solusi yang lebih sederhana. Saya pikir pengkodean saya adalah UTF-8 karena ketika saya mencetak karakter yang menyinggung dengan bantuan halaman ini: Dapatkan nilai unicode dari karakter yang saya temukan itu
\ufeff
. Saya menggunakan kodeSystem.out.println( "\\u" + Integer.toHexString(str.charAt(0) | 0x10000).substring(1) );
untuk mencetak nilai unicode yang menyinggung.Setelah saya mendapatkan nilai unicode yang menyinggung, saya menggantinya di baris pertama file saya sebelum saya melanjutkan membaca. Logika bisnis dari bagian itu:
Ini memperbaiki masalah saya. Kemudian saya dapat melanjutkan memproses file tersebut tanpa masalah. Saya menambahkan
trim()
jika ada spasi kosong di depan atau di belakang, Anda dapat melakukannya atau tidak, berdasarkan kebutuhan spesifik Anda.sumber