Dizeyi UTF-8 olarak kodla


190

"Ñ" karakteri olan bir String var ve onunla bazı sorunlar var. UTF-8 kodlamasına bu String kodlamak gerekiyor. Ben bu şekilde denedim, ama çalışmıyor:

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

Bu dizeyi utf-8'e nasıl kodlayabilirim?


2
Tam olarak ne yapmaya çalıştığınız belli değil. MyString, ñ karakterini doğru bir şekilde içeriyor mu ve onu bir bayt dizisine dönüştürmede sorun yaşıyorsanız (bu durumda Peter ve Amir'in cevaplarına bakın) veya myString bozuk mu ve onu düzeltmeye çalışıyorsunuz (bu durumda Joachim'in cevaplarına bakın) ve ben)?
Michael Borgwardt

MyString utf-8 kodlaması olan bir sunucuya göndermek ve "ñ" karakteri utf-8 kodlaması dönüştürmek gerekiyor.
Alex

1
Eğer bu sunucu UTF-8'i beklerse, onu göndermek için ihtiyacınız olan şey bir Dize değil bayttır. Peter'ın cevabına göre, kodlamayı ilk satırda belirtin ve ikinci satırı bırakın.
Michael Borgwardt

@Michael: Katılıyorum, burada gerçek niyetin ne olduğu açık değil. İnsanların Dizeler ve baytlar arasında dönüşümleri {In,Out}putStream{Read,Writ}erskendileri için yapmasına izin vermek yerine açık bir şekilde ifade etmeye çalıştıkları birçok soru var gibi görünüyor . Nedenini merak ediyorum?
tchrist

1
@Michael: Teşekkürler, sanırım bu mantıklı. Ama aynı zamanda olması gerekenden daha da zorlaştırıyor, değil mi? Bu şekilde çalışan dillerden çok hoşlanmıyorum ve bu yüzden onlarla çalışmaktan kaçınmaya çalışın. Java'nın bayt yerine karakter dizeleri modelinin işleri çok daha kolay hale getirdiğini düşünüyorum. Perl ve Python da “her şey Unicode dizeleri” modelini paylaşıyor. Evet, üçünde de baytlarla çalışabilirsiniz, ancak pratikte gerçekten ihtiyacınız olan nadirdir: bu oldukça düşük seviyedir. Ayrıca ne demek istediğimi biliyorsanız, bir kediyi yanlış yönde fırçalamak gibi hissettiriyor. :)
tchrist

Yanıtlar:


140

String Java'daki nesneler değiştirilemeyen UTF-16 kodlamasını kullanır.

Farklı bir kodlamaya sahip olabilen tek şey bir byte[]. UTF-8 verilerine ihtiyacınız varsa, bir byte[]. StringBeklenmedik veriler içeren bir varsa , sorun bazı ikili verileri yanlış bir şekilde dönüştüren daha önceki bir yerde String(yanlış kodlama kullanıyordu).


92
Teknik olarak konuşursak, byte [] herhangi bir kodlamaya sahip değildir. Bayt dizisi PLUS kodlaması size dize verebilir.
Peter Štibraný

1
@Peter: doğru. Ancak, ona bir kodlama eklemek mantıklıdır, mantıklı byte[]değildir String(kodlama UTF-16 değilse, bu durumda mantıklıdır, ancak yine de gereksiz bilgilerdir).
Joachim Sauer

4
String objects in Java use the UTF-16 encoding that can't be modified. Bu teklif için resmi bir kaynağınız var mı?
Ahmad Hajjar

@AhmadHajjar docs.oracle.com/javase/10/docs/api/java/lang/… : "Java platformu, char dizilerinde ve String ve StringBuffer sınıflarında UTF-16 temsilini kullanır."
Maxi Gis

173

Kullanmaya ne dersiniz?

ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(myString)

Peter ile tartışmamı görün. Ancak soru hakkındaki varsayımı doğruysa, çözümünüz hala bir ByteBuffer döndürdüğü için fikir olmaz.
Michael Borgwardt

8
Ancak kodlanmış bir String'i nasıl edinebilirim? bir ByteBuffer döndürür
Alex

7
@Alex: UTF-8 kodlu Java Dizesi olması mümkün değildir . Bayt istiyorsunuz, bu yüzden ya doğrudan ByteBuffer kullanın (hedefiniz bir ağ koleksiyonu yoluyla göndermekse en iyi çözüm olabilir) ya da bir bayt almak için dizini () çağırın []
Michael Borgwardt

2
Yararlı olabilecek başka bir şey, UnsupportedEncodingException özel durumu oluşturabilecek bir String yerine Guava'nın Charsets.UTF_8 enum değerini kullanmaktır. - String> bayt: myString.getBytes(Charsets.UTF_8)ve bayt -> Dize: new String(myByteArray, Charsets.UTF_8).
laughing_man

24
Daha da iyisi, kullanın StandardCharsets.UTF_8. Java 1.7 ve sonraki sürümlerinde kullanılabilir.
Kat

81

Java7'de şunları kullanabilirsiniz:

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

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

Bunun getBytes(String)beyan etmeme avantajı vardır throws UnsupportedEncodingException.

Eski bir Java sürümü kullanıyorsanız karakter sabitlerini kendiniz bildirebilirsiniz:

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");
    //....
}

2
Bu doğru cevap. Birisi dize veri türü kullanmak istiyorsa, onu doğru biçimde kullanabilir. Yanıtların geri kalanı bayt biçimli türe işaret ediyor.
Neeraj Shukla

6 çalışır. Teşekkürler.
Itsik Mauyhas

Benim için de doğru cevap. Yine de, yukarıdaki gibi kullandığımda, Alman karakteri? Olarak değiştirildi. Yani, bunu kullandım: byte [] ptext = myString.getBytes (UTF_8); Dize değeri = yeni Dize (ptext, UTF_8); Bu iyi çalıştı.
Farhan Hafeez

3
Kod örneği bir anlam ifade etmiyor. Önce ISO-8859-1'e dönüştürürseniz, bu bayt dizisi UTF-8 değildir , bu nedenle sonraki satır tamamen yanlıştır. Elbette, ASCII dizeleri için çalışacaktır ancak o zaman sen de basit bir kopyasını yapabilir: String value = new String(myString);.
Alexis Wilke

76

Yerine byte[] ptext = String.getBytes("UTF-8");kullanın getBytes(). getBytes()UTF-8 olmayabilir "varsayılan kodlama" kullanır.


9
@Michael: açıkça dizeden bayt alma konusunda sorun yaşıyor. GetBytes (kodlama) noktasını nasıl kaçırıyor? Bence ikinci hat sadece onu geri dönüştürüp dönüştüremeyeceğini kontrol etmek için orada.
Peter Štibraný

1
Ben kırık bir dize sahip ve bayt ve geri (ortak yanlış anlama) dönüştürerek "düzeltmek" çalışırken olarak yorumlayın. İkinci satırın sadece sonucu kontrol ettiğine dair gerçek bir gösterge yok.
Michael Borgwardt

@ Michael, hayır yok, bu sadece benim yorumum. Seninki farklı.
Peter Štibraný

1
@Peter: haklısın, Alex'ten gerçekten ne anlama geldiğini açıklığa kavuşturmamız gerekiyordu. Cevap düzenlenmedikçe downvote iptal edilemez ...
Michael Borgwardt

33

Bir Java Dizesi dahili olarak her zaman UTF-16'da kodlanır - ancak bunu böyle düşünmelisiniz: kodlama Dizeler ve baytlar arasında çeviri yapmanın bir yoludur.

Bu nedenle, bir kodlama sorununuz varsa, String'iniz olduğunda, düzeltmek için çok geç. Bu Dizeyi oluşturduğunuz yeri bir dosya, DB veya ağ bağlantısından düzeltmeniz gerekir.


1
Dizelerin dahili olarak UTF-16 olarak kodlandığına inanmak yaygın bir hatadır. Genellikle bunlar, ancak bu yalnızca String sınıfının uygulamaya özel bir ayrıntısıysa. Karakter verilerinin dahili depolamasına genel API aracılığıyla erişilemediğinden, belirli bir String uygulaması başka herhangi bir kodlama kullanmaya karar verebilir.
jarnbjo

4
@jarnbjo: API "Dize UTF-16 biçiminde bir dizeyi temsil eder" ifadesini açıkça belirtir. Dahili biçim olarak başka bir şey kullanmak oldukça verimsiz olur ve bildiğim tüm gerçek uygulamalar UTF-16'yı dahili olarak kullanır. Yani, bunu yapmayan bir alıntı yapamazsanız, oldukça saçma saç dökülmesine giriyorsunuz.
Michael Borgwardt

Kamusal erişim ile veri yapılarının iç temsili arasında ayrım yapmak saçma mıdır?
jarnbjo

6
JVM (VM ile ilgili olduğu sürece) dize kodlaması için örneğin sınıf dosyalarında UTF-8 kullanır. Java.lang.String uygulaması JVM'den ayrılmıştır ve cevabınızın yanlış olduğunu fark etmeniz için gerçekten gerekliyse, iç temsil için başka bir kodlama kullanarak sınıfı sizin için kolayca uygulayabilirim. UTF-16'yı dahili format olarak kullanmak, çoğu zaman bellek tüketimi söz konusu olduğunda da oldukça verimsizdir ve neden gömülü donanım için Java uygulamalarının performans yerine bellek için optimize edilmediğini anlamıyorum.
jarnbjo

1
@jarnbjo: Ve bir kez daha: standart API uygulaması , Dizeleri uygulamak için dahili olarak UTF-16 dışında bir şey kullanan bir JVM'nin somut bir örneğini veremediğiniz sürece, ifadem doğrudur. Ve hayır, String sınıfı, intern () ve sabit havuz gibi şeyler nedeniyle JVM'den gerçekten ayrılmaz.
Michael Borgwardt

22

Bu şekilde deneyebilirsiniz.

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

1
Deli oluyordum. "ISO-8859-1" ilk bayt almak için teşekkür ederiz çözüm oldu.
Gian Gomen

2
Bu yanlış. Dizeniz Unicode karakterleri içeriyorsa, 8859-1'e dönüştürmek bir istisna veya daha kötüsü size geçersiz bir dize (0x100 ve üzeri kod noktasına sahip karakterleri olmayan dize) verir.
Alexis Wilke

12

Bir anda bu problemi yaşadım ve aşağıdaki şekilde çözmeyi başardım

önce almam gerek

import java.nio.charset.Charset;

Sonra kullanmak için bir sabit beyan etmek zorunda kaldı UTF-8veISO-8859-1

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

Sonra aşağıdaki şekilde kullanabilirsiniz:

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);

1
mükemmel çözüm.
Tunde Pizzle

9
String value = new String(myString.getBytes("UTF-8"));

ve "ISO-8859-1" kodlu metin dosyasından okumak istiyorsanız:

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) {
    //...
}

2

Kodlama biçimini belirterek özel karakteri kodlamak için aşağıdaki kodu kullanıyorum.

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");

2

NetBeans varsayılan kodlama UTF-8'in nasıl yapılandırılacağı hakkında hızlı ve adım adım kılavuz. Sonuç olarak NetBeans tüm yeni dosyaları UTF-8 kodlamasında oluşturacaktır.

NetBeans varsayılan kodlama UTF-8 adım adım kılavuzu

  • NetBeans kurulum dizinindeki etc klasörüne gidin

  • Netbeans.conf dosyasını düzenleyin

  • Netbeans_default_options satırını bulun

  • -J-Dfile.encoding = UTF-8'i o satırın içindeki tırnak içine ekleyin

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

  • NetBeans'ı yeniden başlat

NetBeans varsayılan kodlama UTF-8'i ayarlarsınız.

Netbeans_default_options, tırnak işaretleri içinde ek parametreler içerebilir. Bu durumda, dizenin sonuna -J-Dfile.encoding = UTF-8 ekleyin. Diğer parametrelerden boşlukla ayırın.

Misal:

netbeans_default_options = "- J-istemcisi -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 "

daha fazla ayrıntı için link


0

Bu benim sorunumu çözdü

    String inputText = "some text with escaped chars"
    InputStream is = new ByteArrayInputStream(inputText.getBytes("UTF-8"));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.