Codificar cadena a UTF-8

190

Tengo una cadena con un carácter "ñ" y tengo algunos problemas con ella. Necesito codificar esta cadena a la codificación UTF-8. Lo he intentado de esta manera, pero no funciona:

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

¿Cómo codifico esa cadena a utf-8?

Alex
fuente
2
No está claro qué es exactamente lo que estás tratando de hacer. ¿MyString contiene correctamente el carácter ñ y tiene problemas para convertirlo en una matriz de bytes (en ese caso, vea las respuestas de Peter y Amir), o myString está dañado y está tratando de arreglarlo (en ese caso, vea las respuestas de Joachim y yo)?
Michael Borgwardt
Necesito enviar myString a un servidor con codificación utf-8 y necesito convertir el carácter "ñ" a codificación utf-8.
Alex
1
Bueno, si ese servidor espera UTF-8, entonces lo que necesita enviar es bytes, no una cadena. Entonces, según la respuesta de Peter, especifique la codificación en la primera línea y suelte la segunda línea.
Michael Borgwardt
@ Michael: Estoy de acuerdo en que no está claro cuál es la intención real aquí. Parece que hay muchas preguntas en las que las personas intentan realizar conversiones explícitas entre cadenas y bytes en lugar de dejar {In,Out}putStream{Read,Writ}ersque lo hagan por ellas. ¿Me pregunto porque?
tchrist
1
@ Michael: Gracias, supongo que tiene sentido. Pero también lo hace más difícil de lo necesario, ¿no? No soy muy aficionado a los idiomas que funcionan de esa manera, por lo que trato de evitar trabajar con ellos. Creo que el modelo de Java de cadenas de caracteres en lugar de bytes facilita mucho las cosas. Perl y Python también comparten el modelo "todo son cadenas Unicode". Sí, en los tres todavía puedes obtener bytes si trabajas en ello, pero en la práctica parece raro que realmente necesites hacerlo: es un nivel bastante bajo. Además, se siente como cepillar a un gato en la dirección incorrecta, si sabes a lo que me refiero. :)
tchrist

Respuestas:

140

String Los objetos en Java usan la codificación UTF-16 que no se puede modificar.

Lo único que puede tener una codificación diferente es a byte[]. Entonces, si necesita datos UTF-8, entonces necesita a byte[]. Si tiene un Stringarchivo que contiene datos inesperados, entonces el problema está en algún lugar anterior que convirtió incorrectamente algunos datos binarios a a String(es decir, estaba usando la codificación incorrecta).

Joachim Sauer
fuente
92
Técnicamente hablando, el byte [] no tiene ninguna codificación. Sin embargo, la codificación PLUS de bytes puede darle una cadena.
Peter Štibraný
1
@Peter: cierto. Pero adjuntarle una codificación solo tiene sentido byte[], no tiene sentido String(a menos que la codificación sea UTF-16, en cuyo caso tiene sentido pero sigue siendo información innecesaria).
Joachim Sauer
44
String objects in Java use the UTF-16 encoding that can't be modified. ¿Tiene una fuente oficial para esta cita?
Ahmad Hajjar
@AhmadHajjar docs.oracle.com/javase/10/docs/api/java/lang/… : "La plataforma Java utiliza la representación UTF-16 en matrices de caracteres y en las clases String y StringBuffer".
Maxi Gis
173

¿Qué tal usar

ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(myString)
Amir Rachum
fuente
Vea mi discusión con Peter. Pero si su suposición sobre la pregunta es correcta, su solución aún no sería una idea, ya que devuelve un ByteBuffer.
Michael Borgwardt
8
Pero, ¿cómo obtengo una cadena codificada? devuelve un ByteBuffer
Alex
77
@Alex: no es posible tener una cadena Java codificada en UTF-8. Desea bytes, así que use ByteBuffer directamente (incluso podría ser la mejor solución si su objetivo es enviarlo a través de una colección de red) o llame a array () para obtener un byte []
Michael Borgwardt
2
Algo más que puede ser útil es utilizar la enumeración Charsets.UTF_8 de Guava en lugar de una cadena que pueda generar una excepción de codificación no admitida. String -> Bytes: myString.getBytes(Charsets.UTF_8)y bytes -> string: new String(myByteArray, Charsets.UTF_8).
laughing_man
24
Aún mejor, use StandardCharsets.UTF_8. Disponible en Java 1.7+.
Kat
81

En Java7 puedes usar:

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

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

Esto tiene la ventaja sobre getBytes(String)que no declarathrows UnsupportedEncodingException .

Si está utilizando una versión de Java anterior, puede declarar las constantes del juego de caracteres usted mismo:

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
fuente
2
Esta es la respuesta correcta. Si alguien quiere usar un tipo de datos de cadena, puede usarlo en el formato correcto. El resto de las respuestas apuntan al tipo con formato de byte.
Neeraj Shukla
Funciona en 6. Gracias.
Itsik Mauyhas
Respuesta correcta para mí también. Sin embargo, una cosa, cuando utilicé lo anterior, el carácter alemán cambió a? Entonces, usé esto: byte [] ptext = myString.getBytes (UTF_8); Valor de cadena = nueva cadena (ptext, UTF_8); Esto funcionó bien.
Farhan Hafeez
3
El código de muestra no tiene sentido. Si primero convierte a ISO-8859-1, entonces esa matriz de bytes no es UTF-8, por lo que la siguiente línea es totalmente incorrecta. Se trabajará para cadenas de caracteres ASCII, por supuesto, pero entonces usted podría también hacer una copia simple: String value = new String(myString);.
Alexis Wilke
76

Usar en byte[] ptext = String.getBytes("UTF-8");lugar de getBytes(). getBytes()utiliza la llamada "codificación predeterminada", que puede no ser UTF-8.

Peter Štibraný
fuente
9
@ Michael: claramente está teniendo problemas para obtener bytes de la cadena. ¿Cómo es que getBytes (codificación) pierde el punto? Creo que la segunda línea está ahí solo para verificar si puede volver a convertirla.
Peter Štibraný
1
Lo interpreto como si tuviera una cadena rota y tratara de "arreglarlo" mediante la conversión a bytes y viceversa (malentendido común). No hay indicios reales de que la segunda línea solo verifique el resultado.
Michael Borgwardt
@ Michael, no, no lo hay, es solo mi interpretación. El tuyo es simplemente diferente.
Peter Štibraný
1
@ Peter: tienes razón, necesitaríamos una aclaración de Alex sobre lo que realmente quiere decir. No se puede dejar sin efecto la downvote aunque menos que se edita la respuesta ...
Michael Borgwardt
33

Una cadena de Java siempre se codifica internamente en UTF-16, pero realmente debería pensarlo así: una codificación es una forma de traducir entre cadenas y bytes.

Entonces, si tiene un problema de codificación, para cuando tenga String, es demasiado tarde para solucionarlo. Debe arreglar el lugar donde crea esa Cadena desde un archivo, base de datos o conexión de red.

Michael Borgwardt
fuente
1
Es un error común creer que las cadenas están codificadas internamente como UTF-16. Por lo general, lo son, pero si es solo un detalle específico de implementación de la clase String. Dado que el almacenamiento interno de los datos de caracteres no es accesible a través de la API pública, una implementación de cadena específica puede decidir usar cualquier otra codificación.
jarnbjo
3
@jarnbjo: la API indica explícitamente "Una cadena representa una cadena en el formato UTF-16". Usar cualquier otra cosa como formato interno sería muy ineficiente, y todas las implementaciones reales que conozco usan UTF-16 internamente. Entonces, a menos que pueda citar uno que no lo haga, está participando en un corte de cabello bastante absurdo.
Michael Borgwardt
¿Es absurdo distinguir entre el acceso público y la representación interna de las estructuras de datos?
jarnbjo
55
La JVM (en la medida en que sea relevante para la VM) utiliza UTF-8 para la codificación de cadenas, por ejemplo, en los archivos de clase. La implementación de java.lang.String está desacoplada de la JVM y podría implementar fácilmente la clase para usted usando cualquier otra codificación para la representación interna si eso es realmente necesario para que se dé cuenta de que su respuesta es incorrecta. El uso de UTF-16 como formato interno es en la mayoría de los casos altamente ineficiente también en lo que respecta al consumo de memoria y no veo por qué, por ejemplo, las implementaciones de Java para hardware integrado no se optimizarían para la memoria en lugar del rendimiento.
jarnbjo
1
@jarnbjo: Y una vez más: el tiempo que no se puede dar un ejemplo concreto de una JVM cuya implementación de la API estándar de no utilizar internamente algo que no sea UTF-16 para implementar cadenas, mi afirmación es correcta. Y no, la clase String no está realmente desacoplada de la JVM, debido a cosas como intern () y el grupo constante.
Michael Borgwardt
22

Puedes intentarlo de esta manera.

byte ptext[] = myString.getBytes("ISO-8859-1"); 
String value = new String(ptext, "UTF-8"); 
usuario716840
fuente
1
Me estaba volviendo loco. Gracias por obtener los bytes en "ISO-8859-1" primero fue la solución.
Gian Gomen
2
Esto está mal. Si su cadena incluye caracteres Unicode, convertirla a 8859-1 arrojará una excepción o, peor aún, le dará una cadena no válida (tal vez la cadena sin esos caracteres con el punto de código 0x100 y más).
Alexis Wilke
12

En un momento pasé por este problema y logré resolverlo de la siguiente manera

primero necesito importar

import java.nio.charset.Charset;

Luego tuve que declarar una constante para usar UTF-8yISO-8859-1

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

Entonces podría usarlo de la siguiente manera:

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
fuente
1
Solución perfecta.
Tunde Pizzle
9
String value = new String(myString.getBytes("UTF-8"));

y, si desea leer desde un archivo de texto con "ISO-8859-1" codificado:

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
fuente
2

He usado el siguiente código para codificar el carácter especial especificando el formato de codificación.

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
fuente
2

Una guía rápida paso a paso sobre cómo configurar la codificación predeterminada NetBeans UTF-8. En consecuencia, NetBeans creará todos los archivos nuevos en codificación UTF-8.

Guía paso a paso de codificación predeterminada de NetBeans UTF-8

  • Vaya a la carpeta etc. en el directorio de instalación de NetBeans

  • Editar el archivo netbeans.conf

  • Encuentra la línea netbeans_default_options

  • Agregue -J-Dfile.encoding = UTF-8 entre comillas dentro de esa línea

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

  • Reiniciar NetBeans

Configura la codificación predeterminada de NetBeans UTF-8.

Sus netbeans_default_options pueden contener parámetros adicionales dentro de las comillas. En tal caso, agregue -J-Dfile.encoding = UTF-8 al final de la cadena. Separarlo con espacio de otros parámetros.

Ejemplo:

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 = verdadero -J-Dsun.java2d.dpiaware = verdadero -J-Dsun.zip.disableMemoryMapping = verdadero -J-Dfile.encoding = UTF-8 "

aquí hay un enlace para más detalles

Sr. Laeeq Khan
fuente
0

Esto resolvió mi problema

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