Encode String ke UTF-8

190

Saya memiliki String dengan karakter "ñ" dan saya memiliki beberapa masalah dengannya. Saya perlu menyandikan String ini ke pengkodean UTF-8. Saya sudah mencobanya dengan cara ini, tetapi tidak berhasil:

byte ptext[] = myString.getBytes();
String value = new String(ptext, "UTF-8");

Bagaimana cara menyandikan string itu ke utf-8?

Alex
sumber
2
Tidak jelas apa sebenarnya yang Anda coba lakukan. Apakah myString mengandung karakter ñ dengan benar dan Anda memiliki masalah untuk mengubahnya menjadi array byte (dalam hal ini lihat jawaban dari Peter dan Amir), atau myString rusak dan Anda mencoba memperbaikinya (dalam hal itu, lihat jawaban dari Joachim dan saya)?
Michael Borgwardt
Saya perlu mengirim myString ke server dengan pengkodean utf-8 dan saya perlu mengubah karakter "ñ" menjadi pengkodean utf-8.
Alex
1
Nah, jika server itu mengharapkan UTF-8 maka yang Anda butuhkan adalah byte, bukan sebuah String. Jadi sesuai jawaban Peter, tentukan pengkodean di baris pertama dan lepaskan baris kedua.
Michael Borgwardt
@Michael: Saya setuju bahwa tidak jelas apa maksud sebenarnya di sini. Tampaknya ada banyak pertanyaan di mana orang mencoba konversi eksplisit antara String dan byte daripada membiarkannya {In,Out}putStream{Read,Writ}ersmelakukannya untuk mereka. Kenapa ya?
tchrist
1
@Michael: Terima kasih, saya kira itu masuk akal. Tapi itu juga membuatnya lebih sulit dari yang seharusnya, bukan? Saya tidak terlalu menyukai bahasa yang bekerja seperti itu, jadi cobalah untuk tidak bekerja dengan mereka. Saya pikir model Java dari String karakter bukannya byte membuat semuanya jauh lebih mudah. Perl dan Python juga berbagi model "everything is Unicode strings". Ya, dalam ketiganya Anda masih bisa mendapatkan byte jika Anda bekerja di sana, tetapi dalam praktiknya tampaknya jarang bahwa Anda benar-benar perlu: itu cukup rendah. Ditambah lagi rasanya seperti menyikat kucing ke arah yang salah, jika Anda tahu apa yang saya maksud. :)
tchrist

Jawaban:

140

String objek di Java menggunakan pengkodean UTF-16 yang tidak dapat dimodifikasi.

Satu-satunya hal yang dapat memiliki pengkodean yang berbeda adalah a byte[]. Jadi, jika Anda membutuhkan data UTF-8, maka Anda memerlukan byte[]. Jika Anda memiliki Stringyang berisi data yang tidak terduga, maka masalahnya adalah di beberapa tempat sebelumnya yang salah mengkonversi beberapa data biner ke String(yaitu menggunakan pengkodean yang salah).

Joachim Sauer
sumber
92
Secara teknis, byte [] tidak memiliki penyandian. Enkripsi array byte PLUS dapat memberikan Anda string.
Peter Štibraný
1
@ Peter: benar. Tetapi melampirkan suatu pengkodean hanya masuk akal untuk byte[], itu tidak masuk akal untuk String(kecuali pengkodean adalah UTF-16, dalam hal ini masuk akal tetapi masih informasi yang tidak perlu).
Joachim Sauer
4
String objects in Java use the UTF-16 encoding that can't be modified. Apakah Anda memiliki sumber resmi untuk penawaran ini?
Ahmad Hajjar
@AhmadHajjar docs.oracle.com/javase/10/docs/api/java/lang/… : "Platform Java menggunakan representasi UTF-16 dalam array char dan dalam kelas String dan StringBuffer."
Maxi Gis
173

Bagaimana kalau menggunakan

ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(myString)
Amir Rachum
sumber
Lihat diskusi saya dengan Peter. Tetapi jika asumsinya tentang pertanyaan itu benar, solusi Anda masih tidak akan tahu karena mengembalikan ByteBuffer.
Michael Borgwardt
8
Tapi bagaimana cara mendapatkan String yang dikodekan? mengembalikan ByteBuffer
Alex
7
@ Alex: tidak mungkin untuk memiliki Java String yang dikodekan UTF-8. Anda ingin byte, jadi gunakan ByteBuffer secara langsung (bahkan bisa menjadi solusi terbaik jika tujuan Anda adalah mengirimkannya melalui kumpulan jaringan) atau memanggil array () di atasnya untuk mendapatkan byte []
Michael Borgwardt
2
Hal lain yang mungkin bermanfaat adalah menggunakan Charsets Guava.UTF_8 alih-alih String yang dapat melempar UnsupportedEncodingException. String -> byte: myString.getBytes(Charsets.UTF_8), dan byte -> String: new String(myByteArray, Charsets.UTF_8).
laughing_man
24
Bahkan lebih baik, gunakan StandardCharsets.UTF_8. Tersedia di Java 1.7+.
Kat
81

Di Java7 Anda dapat menggunakan:

import static java.nio.charset.StandardCharsets.*;

byte[] ptext = myString.getBytes(ISO_8859_1); 
String value = new String(ptext, UTF_8); 

Ini memiliki keunggulan dibandingkan getBytes(String)yang tidak dinyatakannya throws UnsupportedEncodingException.

Jika Anda menggunakan versi Java yang lebih lama, Anda dapat mendeklarasikan konstanta charset sendiri:

import java.nio.charset.Charset;

public class StandardCharsets {
    public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
    public static final Charset UTF_8 = Charset.forName("UTF-8");
    //....
}
rzymek
sumber
2
Ini adalah jawaban yang benar. Jika seseorang ingin menggunakan tipe data string, ia dapat menggunakannya dalam format yang tepat. Sisa jawaban menunjuk ke tipe byte yang diformat.
Neeraj Shukla
Bekerja di 6. Terima kasih.
Itsik Mauyhas
Jawaban yang benar untuk saya juga. Namun satu hal, ketika saya menggunakan seperti di atas, karakter Jerman berubah menjadi? Jadi, saya menggunakan ini: byte [] ptext = myString.getBytes (UTF_8); Nilai string = String baru (ptext, UTF_8); Ini bekerja dengan baik.
Farhan Hafeez
3
Sampel kode tidak masuk akal. Jika Anda pertama kali mengkonversi ke ISO-8859-1, maka array byte tersebut bukan UTF-8, sehingga baris berikutnya sama sekali tidak benar. Ia akan bekerja untuk string ASCII, tentu saja, tapi kemudian Anda bisa juga membuat salinan sederhana: String value = new String(myString);.
Alexis Wilke
76

Gunakan byte[] ptext = String.getBytes("UTF-8");sebagai ganti getBytes(). getBytes()menggunakan apa yang disebut "pengodean default", yang mungkin bukan UTF-8.

Peter Štibraný
sumber
9
@Michael: dia jelas kesulitan mendapatkan byte dari string. Bagaimana getBytes (encoding) tidak ada gunanya? Saya pikir baris kedua ada hanya untuk memeriksa apakah dia dapat mengubahnya kembali.
Peter Štibraný
1
Saya menafsirkannya sebagai memiliki String yang rusak dan mencoba untuk "memperbaikinya" dengan mengkonversi ke byte dan kembali (kesalahpahaman umum). Tidak ada indikasi aktual bahwa baris kedua hanya memeriksa hasilnya.
Michael Borgwardt
@Michael, tidak ada, itu hanya interpretasi saya. Milikmu sangat berbeda.
Peter Štibraný
1
@ Peter: Anda benar, kami membutuhkan klarifikasi dari Alex apa yang sebenarnya ia maksudkan. Tidak dapat membatalkan downvote kecuali jika jawabannya diedit ...
Michael Borgwardt
33

String Java secara internal selalu dikodekan dalam UTF-16 - tetapi Anda benar-benar harus memikirkannya seperti ini: pengkodean adalah cara untuk menerjemahkan antara Strings dan byte.

Jadi jika Anda memiliki masalah penyandian, pada saat Anda memiliki String, sudah terlambat untuk memperbaikinya. Anda perlu memperbaiki tempat Anda membuat String dari file, DB atau koneksi jaringan.

Michael Borgwardt
sumber
1
Ini adalah kesalahan umum untuk percaya bahwa string dikodekan secara internal sebagai UTF-16. Biasanya mereka, tetapi jika, itu hanya implementasi detail spesifik dari kelas String. Karena penyimpanan internal data karakter tidak dapat diakses melalui API publik, implementasi String tertentu dapat memutuskan untuk menggunakan pengkodean lainnya.
jarnbjo
3
@jarnbjo: API secara eksplisit menyatakan "String mewakili string dalam format UTF-16". Menggunakan apa pun sebagai format internal akan sangat tidak efisien, dan semua implementasi aktual yang saya tahu menggunakan UTF-16 secara internal. Jadi, kecuali Anda bisa mengutip salah satu yang tidak, Anda terlibat dalam penataan rambut yang sangat tidak masuk akal.
Michael Borgwardt
Apakah tidak masuk akal untuk membedakan antara akses publik dan representasi internal dari struktur data?
jarnbjo
5
JVM (sejauh ini relevan dengan VM sama sekali) menggunakan UTF-8 untuk pengkodean string, misalnya dalam file kelas. Implementasi java.lang.String dipisahkan dari JVM dan saya dapat dengan mudah mengimplementasikan kelas untuk Anda menggunakan pengkodean lain untuk representasi internal jika itu benar-benar diperlukan bagi Anda untuk menyadari bahwa jawaban Anda salah. Menggunakan UTF-16 sebagai format internal dalam banyak kasus sangat tidak efisien juga ketika menyangkut konsumsi memori dan saya tidak melihat mengapa mis. Implementasi Java untuk perangkat keras yang disematkan tidak akan mengoptimalkan memori daripada kinerja.
jarnbjo
1
@jarnbjo: Dan sekali lagi: selama Anda tidak bisa memberikan contoh konkret dari JVM yang pelaksanaannya API standar yang secara internal menggunakan sesuatu selain UTF-16 untuk melaksanakan Strings, pernyataan saya benar. Dan tidak, kelas String tidak benar-benar dipisahkan dari JVM, karena hal-hal seperti intern () dan kumpulan konstan.
Michael Borgwardt
22

Anda bisa coba cara ini.

byte ptext[] = myString.getBytes("ISO-8859-1"); 
String value = new String(ptext, "UTF-8"); 
pengguna716840
sumber
1
Saya menjadi gila. Terima kasih untuk mendapatkan byte di "ISO-8859-1" pertama adalah solusinya.
Gian Gomen
2
Ini salah. Jika string Anda menyertakan karakter Unicode, mengonversinya menjadi 8859-1 akan membuat pengecualian atau lebih buruk memberikan Anda string yang tidak valid (mungkin string tanpa karakter tersebut dengan titik kode 0x100 atau lebih).
Alexis Wilke
12

Sejenak saya melewati masalah ini dan berhasil menyelesaikannya dengan cara berikut

pertama saya perlu mengimpor

import java.nio.charset.Charset;

Kemudian saya harus mendeklarasikan konstanta untuk digunakan UTF-8danISO-8859-1

private static final Charset UTF_8 = Charset.forName("UTF-8");
private static final Charset ISO = Charset.forName("ISO-8859-1");

Maka saya bisa menggunakannya dengan cara berikut:

String textwithaccent="Thís ís a text with accent";
String textwithletter="Ñandú";

text1 = new String(textwithaccent.getBytes(ISO), UTF_8);
text2 = new String(textwithletter.getBytes(ISO),UTF_8);
Quimbo
sumber
1
solusi sempurna.
Tunde Pizzle
9
String value = new String(myString.getBytes("UTF-8"));

dan, jika Anda ingin membaca dari file teks dengan kode "ISO-8859-1" yang disandikan:

String line;
String f = "C:\\MyPath\\MyFile.txt";
try {
    BufferedReader br = Files.newBufferedReader(Paths.get(f), Charset.forName("ISO-8859-1"));
    while ((line = br.readLine()) != null) {
        System.out.println(new String(line.getBytes("UTF-8")));
    }
} catch (IOException ex) {
    //...
}
fedesanp
sumber
2

Saya telah menggunakan kode di bawah ini untuk menyandikan karakter khusus dengan menentukan format penyandian.

String text = "This is an example é";
byte[] byteText = text.getBytes(Charset.forName("UTF-8"));
//To get original string from byte.
String originalString= new String(byteText , "UTF-8");
laxman954
sumber
2

Panduan langkah demi langkah cepat cara mengkonfigurasi NetBeans encoding default UTF-8. Sebagai hasilnya, NetBeans akan membuat semua file baru dalam pengkodean UTF-8.

NetBeans penyandian standar panduan langkah demi langkah UTF-8

  • Buka folder dll di direktori instalasi NetBeans

  • Edit file netbeans.conf

  • Temukan baris netbeans_default_options

  • Tambahkan -J-Dfile.encoding = UTF-8 di dalam tanda kutip di dalam baris itu

    (contoh netbeans_default_options="-J-Dfile.encoding=UTF-8":)

  • Mulai ulang NetBeans

Anda menetapkan NetBeans penyandian standar UTF-8.

Netbeans_default_options Anda mungkin berisi parameter tambahan di dalam tanda kutip. Dalam kasus seperti itu, tambahkan -J-Dfile.encoding = UTF-8 di akhir string. Pisahkan dengan ruang dari parameter lain.

Contoh:

netbeans_default_options = "- J-client -J-Xss128m -J-Xms256m -J-XX: PermSize = 32m -J-Dapple.laf.useScreenMenuBar = true -J-Dapple.awt.graphics.UseQuartz = true -J-Dsun. java2d.noddraw = true -J-Dsun.java2d.dpiaware = true -J-Dsun.zip.disableMemoryMapping = true -J-Dfile.encoding = UTF-8 "

di sini adalah tautan untuk Rincian Lebih Lanjut

Tuan Laeeq Khan
sumber
0

Ini menyelesaikan masalah saya

    String inputText = "some text with escaped chars"
    InputStream is = new ByteArrayInputStream(inputText.getBytes("UTF-8"));
Prasanth RJ
sumber