"¡Hola, amigo!"

"Ahora es el momento de otro tema interesante: las codificaciones".

"Quizás ya hayas escuchado en alguna parte que cada carácter tiene un código (número). Es por eso que el tipo char puede representar tanto símbolos como números".

"Por ejemplo, el código para la letra 'A' en el alfabeto inglés es 65. 'B' es 66, 'C' es 67, etc. Hay códigos únicos para letras mayúsculas, minúsculas, letras cirílicas, letras chinas caracteres (sí, montones, montones de códigos), números y varios símbolos. En resumen, hay un código para prácticamente todo lo que llamarías un personaje".

"Entonces, ¿cada letra y carácter corresponde a algún número?"

"Precisamente."

"Un carácter se puede convertir en un número y un número en un carácter. Java generalmente no ve una diferencia entre ellos:"

char c = 'A'; //The code (number) for 'A' is 65
c++; //Now c contains the number 66, which is the code for 'B'

"Interesante."

"Entonces, una codificación es un conjunto de símbolos y su correspondiente conjunto de códigos. Pero no se ha inventado una sola codificación, hay bastantes. No fue hasta más tarde que se inventó una codificación universal común, Unicode".

"Pero no importa cuántos estándares universales se inventen, nadie tiene prisa por abandonar los viejos. Y luego todo sucede como en esta caricatura:"

Codificaciones de caracteres - 1

"Imagina que Vincent y Nick deciden hacer sus propias codificaciones".

"Aquí está la codificación de Vincent:"
Codificaciones de caracteres - 2

"Y aquí está la codificación de Nick:"
Codificaciones de caracteres - 3

"Incluso usan los mismos caracteres, pero los códigos de los caracteres son diferentes".

"Cuando la cadena 'ABC-123' se escribe en un archivo usando la codificación de Vincent, obtenemos el siguiente conjunto de bytes:"
Codificaciones de caracteres - 4

"Y ahora otro programa que usa la codificación de Nick quiere leer el archivo:"

"Esto es lo que leerá: «345-IJK»."

"Y lo peor es que las codificaciones generalmente no se almacenan en ningún lugar de los archivos, por lo que los desarrolladores tienen que adivinar".

"Bueno, ¿cómo los adivinan?"

"Ese es un tema diferente. Pero quiero explicar cómo trabajar con codificaciones. Como ya sabe, el tamaño de un carácter en Java es de dos bytes. Y Java Strings usa el formato Unicode".

"Pero Java te permite convertir un String en un conjunto de bytes en cualquier codificación que conozca. La clase String tiene métodos especiales para esto. Java también tiene una clase Charset especial que describe una codificación específica".

1) ¿Cómo obtengo una lista de todas las codificaciones que admite Java?

"Hay un método estático especial llamado availableCharsets para eso. "Este método devuelve un conjunto de pares (nombre de codificación, objeto que describe la codificación):"

SortedMap<String,Charset> charsets = Charset.availableCharsets();

"Cada codificación tiene un nombre único. Estos son algunos de ellos: UTF-8, UTF-16, Windows-1251, KOI8-R,..."

2) ¿Cómo obtengo la codificación activa actual (Unicode)?

"Hay un método especial llamado defaultCharset para eso.

Charset currentCharset = Charset.defaultCharset();

3) ¿Cómo convierto una cadena a una codificación específica?

"En Java, puede convertir una cadena en una matriz de bytes en cualquier codificación que Java conozca:"

Método Ejemplo
byte[] getBytes()
String s = "Good news, everyone!";
byte[] buffer = s.getBytes()
byte[] getBytes(Charset charset)
String s = "Good news, everyone!";
Charset koi8 = Charset.forName("KOI8-R");
byte[] buffer = s.getBytes(koi8);
byte[] getBytes(String charsetName)
String s = "Good news, everyone!";
byte[] buffer = s.getBytes("Windows-1251")

4) ¿Cómo puedo convertir una matriz de bytes que leí de un archivo a una cadena, si sé cuál era su codificación en el archivo?

"Esto es aún más fácil. La clase String tiene un constructor especial:"

Método Ejemplo
String(byte bytes[])
byte[] buffer = new byte[1000];
inputStream.read(buffer);

String s = new String(buffer);
String(byte bytes[], Charset charset)
byte[] buffer = new byte[1000];
inputStream.read(buffer);

Charset koi8 = Charset.forName("KOI8-R");
String s = new String(buffer, koi8);
String(byte bytes[], String charsetName)
byte[] buffer = new byte[1000];
inputStream.read(buffer);

String s = new String(buffer, "Windows-1251");

5) ¿Cómo convierto una matriz de bytes de una codificación a otra?

"Hay muchas maneras. Esta es una de las más simples:"

Charset koi8 = Charset.forName("KOI8-R");
Charset windows1251 = Charset.forName("Windows-1251");

byte[] buffer = new byte[1000];
inputStream.read(buffer);
String s = new String(buffer, koi8);
buffer = s.getBytes(windows1251);
outputStream.write(buffer);

"Eso es lo que pensé. Gracias por la interesante lección, Rishi".