Masalah charset membingungkan dan rumit dengan sendirinya, tetapi di atas itu Anda harus mengingat nama persis rangkaian karakter Anda. Apakah itu "utf8"
? Atau "utf-8"
? Atau mungkin "UTF-8"
? Saat mencari sampel kode di internet Anda akan melihat semua hal di atas. Mengapa tidak membuat mereka dinamakan konstanta dan digunakan Charset.UTF8
?
java
character-encoding
serg
sumber
sumber
MessageDigest#getInstance()
.Jawaban:
Jawaban sederhana untuk pertanyaan yang diajukan adalah bahwa string charset yang tersedia bervariasi dari platform ke platform.
Namun, ada enam yang diperlukan untuk hadir, sehingga konstanta bisa dibuat untuk yang sudah lama. Saya tidak tahu mengapa tidak.
JDK 1.4 melakukan hal yang hebat dengan memperkenalkan tipe Charset. Pada titik ini, mereka tidak akan ingin memberikan konstanta String lagi, karena tujuannya adalah untuk membuat semua orang menggunakan instance Charset. Jadi mengapa tidak memberikan enam konstanta standar Charset? Saya bertanya kepada Martin Buchholz karena dia kebetulan duduk tepat di sebelah saya, dan dia mengatakan tidak ada alasan yang sangat bagus, kecuali bahwa pada saat itu, masih setengah matang - terlalu sedikit API JDK telah dipasang untuk menerima Charset, dan dari yang ada, kelebihan Charset biasanya berkinerja lebih buruk.
Sangat menyedihkan bahwa hanya di JDK 1.6 yang akhirnya mereka selesaikan dengan overload Charset. Dan bahwa situasi kinerja terbelakang ini masih ada (alasan mengapa sangat aneh dan saya tidak dapat menjelaskannya, tetapi terkait dengan keamanan!).
Singkat cerita - tetapkan saja konstanta Anda sendiri, atau gunakan kelas Guava's Charsets yang dihubungkan dengan Tony the Pony (meskipun perpustakaan itu belum benar-benar dirilis).
Memperbarui: a
StandardCharsets
kelas di JDK 7.sumber
String(byte bytes[], int offset, int length, Charset charset)
diterapkan. Bahkan, hit kinerja tidak sepele sama sekali ketika membuat string kecil dari byte besar [].Dua tahun kemudian, dan Java 7's StandardCharsets sekarang mendefinisikan konstanta untuk 6 charset standar.
Jika Anda terjebak pada Java 5/6, Anda dapat menggunakan konstanta Guava's Charsets , seperti yang disarankan oleh Kevin Bourrillion dan Jon Skeet.
sumber
Saya berpendapat bahwa kita dapat melakukan jauh lebih baik dari itu ... mengapa charset yang dijamin tidak dapat diakses secara langsung?
Charset.UTF8
harus menjadi referensi keCharset
, bukan nama sebagai string. Dengan begitu kita tidak perlu menanganiUnsupportedEncodingException
semua tempat.Pikiran Anda, saya juga berpikir bahwa .NET memilih strategi yang lebih baik dengan default ke UTF-8 di mana-mana. Itu kemudian mengacaukan dengan menamai properti pengkodean "sistem operasi standar"
Encoding.Default
- yang bukan standar dalam. NET itu sendiri :(Kembali mengomentari dukungan Java charset - mengapa tidak ada konstruktor untuk
FileWriter
/FileReader
yang membutuhkanCharset
? Pada dasarnya itu adalah kelas yang hampir tidak berguna karena pembatasan itu - Anda hampir selalu membutuhkanInputStreamReader
sekitarFileInputStream
atau yang setara untuk output :(Perawat, perawat - di mana obat saya?
EDIT: Terpikir oleh saya bahwa ini belum benar-benar menjawab pertanyaan. Jawaban yang sebenarnya mungkin adalah "tidak ada yang terlibat memikirkannya" atau "seseorang yang terlibat berpikir itu adalah ide yang buruk." Saya akan sangat menyarankan bahwa kelas utilitas internal yang menyediakan nama atau rangkaian karakter menghindari duplikasi di sekitar basis kode ... Atau Anda bisa menggunakan yang kami gunakan di Google ketika jawaban ini pertama kali ditulis . (Perhatikan bahwa pada Java 7, Anda hanya akan menggunakannya
StandardCharsets
.)sumber
Di Jawa 1.7
import java.nio.charset.StandardCharsets
ex:
StandardCharsets.UTF_8
StandardCharsets.US_ASCII
sumber
Keadaan saat ini dari penyandian API meninggalkan sesuatu yang diinginkan. Beberapa bagian dari Java 6 API tidak menerima
Charset
di tempat string (dilogging
,dom.ls
,PrintStream
; mungkin ada orang lain). Tidak membantu bahwa penyandian seharusnya memiliki nama kanonik yang berbeda untuk berbagai bagian dari perpustakaan standar.Saya bisa mengerti bagaimana segala sesuatunya sampai di tempat mereka berada; tidak yakin saya punya ide cemerlang tentang cara memperbaikinya.
Selain itu ...
Anda dapat mencari nama untuk implementasi Java 6 Java di sini .
Untuk UTF-8, nilai kanonik adalah
"UTF-8"
untukjava.nio
dan"UTF8"
untukjava.lang
danjava.io
. Satu-satunya penyandian yang dibutuhkan JRE untuk didukung adalah: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16 .sumber
Saya sudah lama mendefinisikan kelas utilitas dengan konstanta UTF_8, ISO_8859_1 dan US_ASCII Charset.
Juga, beberapa waktu yang lalu (2 + tahun) saya melakukan tes kinerja sederhana antara
new String( byte[], Charset )
dannew String( byte[], String charset_name )
dan menemukan bahwa pelaksanaan terakhir adalah jauh lebih cepat. Jika Anda melihat di bawah kap di kode sumber Anda akan melihat bahwa mereka memang mengikuti jalur yang sangat berbeda.Untuk alasan itu saya memasukkan sebuah utilitas di kelas yang sama
Mengapa konstruktor String (byte [], Charset) tidak melakukan hal yang sama, mengalahkan saya.
sumber
Charset
perlu didaftarkan, sehingga pengecualian bisa terjadi. IIRC, ada beberapa perubahan di JDK7 untuk membuatnya lebih cepat untukCharset
implementasi yang dikenal baik (menghilangkan salinan tambahan).