"Olá, amigo!"

"Agora é hora de outro tópico interessante: codificações."

"Talvez você já tenha ouvido em algum lugar que cada caractere possui um código (número). É por isso que o tipo char pode representar tanto símbolos quanto números."

"Por exemplo, o código para a letra 'A' no alfabeto inglês é 65. 'B' é 66, 'C' é 67 e assim por diante. Existem códigos exclusivos para letras maiúsculas, letras minúsculas, letras cirílicas, letras chinesas caracteres (sim, muitos e muitos códigos), números e vários símbolos. Resumindo, existe um código para praticamente tudo que você chamaria de caractere."

"Então, cada letra e caractere corresponde a algum número?"

"Precisamente."

"Um caractere pode ser convertido em um número e um número em um caractere. Java geralmente não vê diferença entre eles:"

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

"Interessante."

"Portanto, uma codificação é um conjunto de símbolos e seu correspondente conjunto de códigos. Mas não apenas uma codificação foi inventada - existem algumas. Foi só mais tarde que uma codificação universal comum, o Unicode, foi inventada."

"Mas não importa quantos padrões universais sejam inventados, ninguém tem pressa em abandonar os antigos. E então tudo acontece exatamente como neste desenho animado:"

Codificações de caracteres - 1

"Imagine que Vincent e Nick decidam fazer suas próprias codificações."

"Aqui está a codificação de Vincent:"
Codificações de caracteres - 2

"E aqui está a codificação de Nick:"
Codificações de caracteres - 3

"Eles até usam os mesmos caracteres, mas os códigos para os personagens são diferentes."

"Quando a string 'ABC-123' é gravada em um arquivo usando a codificação de Vincent, obtemos o seguinte conjunto de bytes:"
Codificações de caracteres - 4

"E agora outro programa que usa a codificação de Nick quer ler o arquivo:"

"Aqui está o que vai ler: «345-IJK»."

"E o pior é que as codificações normalmente não são armazenadas em nenhum lugar nos arquivos, então os desenvolvedores precisam adivinhar."

"Bem, como eles adivinham?"

"Esse é um assunto diferente. Mas eu quero explicar como trabalhar com codificações. Como você já sabe, o tamanho de um char em Java é de dois bytes. E Java Strings usa o formato Unicode."

"Mas Java permite que você converta um String em um conjunto de bytes em qualquer codificação que ele conheça. A classe String possui métodos especiais para isso. Java também possui uma classe Charset especial que descreve uma codificação específica."

1) Como obtenho uma lista de todas as codificações que o Java suporta?

"Existe um método estático especial chamado availableCharsets para isso. "Este método retorna um conjunto de pares (nome da codificação, objeto que descreve a codificação):"

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

"Cada codificação tem um nome único. Aqui estão alguns deles: UTF-8, UTF-16, Windows-1251, KOI8-R,…"

2) Como obtenho a codificação ativa atual (Unicode)?

"Existe um método especial chamado defaultCharset para isso.

Charset currentCharset = Charset.defaultCharset();

3) Como faço para converter uma String para uma codificação específica?

"Em Java, você pode converter uma String em uma matriz de bytes em qualquer codificação que o Java conheça:"

Método Exemplo
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) Como faço para converter um array de bytes que li de um arquivo para uma String, se eu sei qual era a codificação dele no arquivo?

"Isto é ainda mais fácil. A classe String tem um construtor especial:"

Método Exemplo
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) Como faço para converter uma matriz de bytes de uma codificação para outra?

"Existem muitas maneiras. Aqui está uma das mais 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);

"Isso é o que eu pensei. Obrigado pela lição interessante, Rishi."