Codificați șirul în UTF-8 (Programare, Java, Utf 8)

Alex a intrebat.

Am un String cu un caracter „ñ” și am câteva probleme cu el. Am nevoie să codific acest String în codificarea UTF-8. Am încercat în acest mod, dar nu funcționează:

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

Cum pot codifica acest șir în UTF-8?

Comentarii

  • Nu este clar ce anume încercați să faceți. Șirul meu conține corect caracterul ñ și aveți probleme în a-l converti într-un array de octeți (în acest caz, vedeți răspunsurile lui Peter și Amir), sau Șirul meu este corupt și încercați să îl reparați (în acest caz, vedeți răspunsurile lui Joachim și ale mele)? –  > Por Michael Borgwardt.
  • Trebuie să trimit myString către un server cu codificare utf-8 și trebuie să convertesc caracterul „ñ” în codificare utf-8. –  > Por Alex.
  • Ei bine, dacă serverul respectiv se așteaptă la UTF-8, atunci ceea ce trebuie să îi trimiți sunt octeți, nu un String. Deci, conform răspunsului lui Peter, specificați codificarea în prima linie și renunțați la a doua linie. –  > Por Michael Borgwardt.
  • @Michael: Sunt de acord că nu este clar care este adevărata intenție aici. Se pare că există o mulțime de întrebări în care oamenii încearcă să facă conversii explicite între Strings și bytes, în loc să lase {In,Out}putStream{Read,Writ}ers să o facă pentru ei. Mă întreb de ce? –  > Por tchrist.
  • @Michael: Mulțumesc, presupun că are sens. Dar, de asemenea, face mai greu decât trebuie să fie, nu-i așa? Nu sunt foarte atașat de limbajele care funcționează în acest fel și, prin urmare, încerc să evit să lucrez cu ele. Cred că modelul Java de șiruri de caractere în loc de octeți face lucrurile mult mai ușoare. Perl și Python împărtășesc, de asemenea, modelul „totul este format din șiruri Unicode”. Da, în toate cele trei poți ajunge în continuare la bytes dacă te străduiești, dar în practică pare rar să fie cu adevărat necesar: este un nivel destul de scăzut. În plus, se simte cam ca și cum ai peria o pisică în direcția greșită, dacă înțelegeți ce vreau să spun. 🙂 –  > Por tchrist.
11 răspunsuri
Joachim Sauer

String obiectele din Java folosesc codificarea UTF-16 care nu poate fi modificată.

Singurul lucru care poate avea o codificare diferită este un fișier byte[]. Deci, dacă aveți nevoie de date UTF-8, atunci aveți nevoie de un byte[]. Dacă aveți un String care conține date neașteptate, atunci problema se află într-un loc anterior care a convertit incorect niște date binare în a String (adică a folosit o codificare greșită).

Comentarii

    93

  • Din punct de vedere tehnic, byte[] nu are nicio codificare. Cu toate acestea, array-ul de octeți PLUS encoding poate da șiruri de caractere. –  > Por Peter Štibraný.
  • @Peter: adevărat. Dar atașarea unei codificări la acesta are sens doar pentru byte[], , nu are sens pentru String (cu excepția cazului în care codificarea este UTF-16, caz în care are sens, dar este totuși o informație inutilă). –  > Por Joachim Sauer.
  • String objects in Java use the UTF-16 encoding that can't be modified. Aveți o sursă oficială pentru acest citat? –  > Por Ahmad Hajjar.
  • @AhmadHajjar docs.oracle.com/javase/10/docs/api/java/lang/… : „Platforma Java utilizează reprezentarea UTF-16 în array-urile de caractere și în clasele String și StringBuffer.” –  > Por Maxi Gis.
Amir Rachum

Ce-ar fi să folosiți

ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(myString)

Comentarii

  • Dar cum pot obține un String codificat? returnează un ByteBuffer –  > Por Alex.
  • @Alex: este nu este posibil de a avea un șir de caractere Java codificat UTF-8. Doriți octeți, așa că fie folosiți direct ByteBuffer (ar putea fi chiar cea mai bună soluție dacă scopul dvs. este de a-l trimite prin intermediul unei colecții de rețea), fie apelați array() pe acesta pentru a obține un byte[] –  > Por Michael Borgwardt.
  • Un alt lucru care ar putea fi util este să folosiți enum-ul Charsets.UTF_8 din Guava în loc de un String, care poate arunca o UnsupportedEncodingException. String -> bytes: myString.getBytes(Charsets.UTF_8), , și bytes -> String: new String(myByteArray, Charsets.UTF_8). –  > Por laughing_man.
  • 24

  • Chiar mai bine, folosiți StandardCharsets.UTF_8. Disponibil în Java 1.7+. –  > Por Kat.
  • Matricea returnată de array() va fi, cel mai probabil, mai mare decât este necesar și va fi umplut, deoarece este vorba despre ByteBuffers array intern. Este mai bine să utilizați string.getBytes(StandardCharsets.UTF_8) care va returna un nou array cu dimensiunea corectă. –  > Por Chirlo.
rzymek

În Java7 puteți utiliza:

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

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

Acest lucru are avantajul față de getBytes(String) că nu declară throws UnsupportedEncodingException.

Dacă utilizați o versiune mai veche de Java, puteți declara singuri constantele charset:

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

Comentarii

  • Acesta este răspunsul corect. Dacă cineva dorește să utilizeze un tip de date de tip șir de caractere, îl poate utiliza în formatul corect. Restul răspunsurilor indică tipul format byte. –  > Por Neeraj Shukla.
  • Lucrări în 6. Mulțumesc. –  > Por Itsik Mauyhas.
  • Răspuns corect și pentru mine. Un singur lucru, totuși, când am folosit ca mai sus, caracterul german s-a schimbat în ?. Așa că am folosit următorul lucru: byte[] ptext = myString.getBytes(UTF_8); String value = new String(ptext, UTF_8); A funcționat bine. –  > Por Farhan Hafeez.
  • Exemplul de cod nu are sens. Dacă faceți mai întâi conversia la ISO-8859-1, atunci acea matrice de octeți este nu UTF-8, deci următoarea linie este total incorectă. Va funcționa pentru șirurile ASCII, desigur, dar atunci ai putea la fel de bine să faci o copie simplă: String value = new String(myString);. –  > Por Alexis Wilke.
Peter Štibraný

Utilizați byte[] ptext = String.getBytes("UTF-8"); în loc de getBytes(). getBytes() utilizează așa-numita „codificare implicită”, care poate să nu fie UTF-8.

Comentarii

  • @Michael: este clar că are probleme în a obține octeți din șir. Cum de getBytes(encoding) ratează esențialul? Cred că a doua linie este acolo doar pentru a verifica dacă poate să o convertească înapoi. –  > Por Peter Štibraný.
  • Eu îl interpretez ca având un String stricat și încercând să îl „repare” prin conversia în bytes și înapoi (neînțelegere comună). Nu există nicio indicație reală că a doua linie este doar verificarea rezultatului. –  > Por Michael Borgwardt.
  • @Michael, nu, nu există, este doar interpretarea mea. A ta este pur și simplu diferită. –  > Por Peter Štibraný.
  • @Peter: ai dreptate, am avea nevoie de clarificări din partea lui Alex despre ce vrea să spună cu adevărat. Nu pot totuși să anulez downvote-ul decât dacă răspunsul este editat… –  > Por Michael Borgwardt.
Michael Borgwardt

Un șir de caractere Java este întotdeauna codificat în mod intern în UTF-16 – dar ar trebui să vă gândiți la acest lucru astfel: o codificare este o modalitate de a traduce între șiruri și octeți.

Așadar, dacă aveți o problemă de codificare, în momentul în care aveți String, este prea târziu pentru a o rezolva. Trebuie să remediați locul în care creați acel String dintr-un fișier, BD sau conexiune de rețea.

Comentarii

  • Este o greșeală frecventă să credem că șirurile sunt codificate intern ca UTF-16. De obicei, așa este, dar dacă este cazul, este doar un detaliu specific implementării clasei String. Deoarece stocarea internă a datelor de caractere nu este accesibilă prin intermediul API-ului public, o implementare String specifică poate decide să utilizeze orice altă codificare. –  > Por jarnbjo.
  • @jarnbjo: API-ul afirmă în mod explicit „Un String reprezintă un șir de caractere în format UTF-16”. Folosirea oricărui alt format intern ar fi extrem de ineficientă, iar toate implementările actuale pe care le cunosc folosesc UTF-16 la nivel intern. Așa că, dacă nu poți cita una care nu o face, te angajezi într-o împărțire absurdă a firelor de păr. –  > Por Michael Borgwardt.
  • Este absurd să se facă distincția între accesul public și reprezentarea internă a structurilor de date? –  > Por jarnbjo.
  • JVM (în măsura în care acest lucru este relevant pentru VM) utilizează UTF-8 pentru codificarea șirurilor de caractere, de exemplu în fișierele de clasă. Implementarea java.lang.String este decuplabilă de JVM și aș putea implementa cu ușurință clasa pentru dvs. folosind orice altă codificare pentru reprezentarea internă, dacă acest lucru este cu adevărat necesar pentru ca dvs. să vă dați seama că răspunsul dvs. este incorect. Utilizarea UTF-16 ca format intern este, în majoritatea cazurilor, foarte ineficientă și în ceea ce privește consumul de memorie și nu văd de ce, de exemplu, implementările Java pentru hardware încorporat nu ar optimiza memoria în locul performanței. –  > Por jarnbjo.
  • @jarnbjo: Și încă o dată: atâta timp cât nu puteți da un exemplu concret de JVM a cărui implementare API standard face utilizează în mod intern altceva decât UTF-16 pentru a implementa Strings, afirmația mea este corectă. Și nu, clasa String nu este cu adevărat decuplată de JVM, datorită unor lucruri precum intern() și fondul de constante. –  > Por Michael Borgwardt.
user716840

Puteți încerca în acest fel.

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

Comentarii

  • Eu o luam razna. Mulțumesc pentru a obține mai întâi octeții în „ISO-8859-1” a fost soluția. –  > Por jan4co.
  • Acest lucru este greșit. Dacă șirul dvs. include caractere Unicode, convertirea în 8859-1 va arunca o excepție sau, mai rău, vă va da un șir invalid (poate șirul fără acele caractere cu punctul de cod 0x100 și peste). –  > Por Alexis Wilke.
Quimbo

Într-o clipă am trecut prin această problemă și am reușit să o rezolv în felul următor

mai întâi trebuie să import

import java.nio.charset.Charset;

Apoi a trebuit să declar o constantă pe care să o folosesc UTF-8 și ISO-8859-1

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

Apoi am putut să o folosesc în felul următor:

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

Comentarii

  • soluție perfectă. –  > Por Tunde Pizzle.
fedesanp
String value = new String(myString.getBytes("UTF-8"));

și, dacă doriți să citiți dintr-un fișier text cu codificare „ISO-8859-1”:

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

laxman954

Am folosit codul de mai jos pentru a codifica caracterul special prin specificarea formatului de codificare.

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

Domnul Laeeq Khan

Un ghid rapid, pas cu pas, despre cum să configurați codificarea implicită UTF-8 a NetBeans. În rezultat, NetBeans va crea toate fișierele noi în codificarea UTF-8.

Ghid pas cu pas NetBeans pentru codificarea implicită UTF-8

  • Mergeți la folderul etc. din directorul de instalare NetBeans

  • Editați fișierul netbeans.conf

  • Găsiți linia netbeans_default_options

  • Adăugați -J-Dfile.encoding=UTF-8 între ghilimele în interiorul acestei linii

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

  • Reporniți NetBeans

Ați setat codificarea implicită UTF-8 pentru NetBeans.

Opțiunile dvs. netbeans_default_options pot conține parametri suplimentari în interiorul ghilimelelor. În acest caz, adăugați -J-Dfile.encoding=UTF-8 la sfârșitul șirului. Separați-l cu spațiu de ceilalți parametri.

Exemplu:

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″

aici este link-ul pentru detalii suplimentare

Prasanth RJ

Acest lucru a rezolvat problema mea

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

Tags:,