Noções básicas do conjunto de caracteres:
Conjunto de caracteres
Uma coleção de caracteres, ou seja, símbolos com semântica especial. A letra "A" é um caractere. "%" também é um caractere. Não possui valor numérico intrínseco e não possui conexão direta com ASC II, Unicode ou mesmo computadores. Os símbolos existiam muito antes dos computadores.
Conjunto de caracteres codificados
Um valor numérico é atribuído a uma coleção de caracteres. Atribua códigos aos caracteres para que eles possam expressar resultados numéricos usando um conjunto específico de codificação de caracteres. Outros conjuntos de caracteres codificados podem atribuir valores diferentes ao mesmo caractere. Os mapeamentos de conjuntos de caracteres geralmente são determinados por organizações de padronização, como USASCII, ISO 8859-1, Unicode (ISO 10646-1) e JIS X0201.
Esquema de codificação de caracteres
Mapeamento de membros do conjunto de caracteres codificados para octetos (bytes de 8 bits). Um esquema de codificação define como uma sequência de codificações de caracteres é expressa como uma sequência de bytes. O valor da codificação de caracteres não precisa ser igual ao byte de codificação, nem precisa ser um relacionamento um para um ou um para muitos. Em princípio, a codificação e decodificação de conjuntos de caracteres podem ser aproximadas como serialização e desserialização de objetos.
Normalmente, a codificação de dados de caracteres é usada para transmissão em rede ou armazenamento de arquivos. Um esquema de codificação não é um conjunto de caracteres, é um mapeamento, mas devido ao seu relacionamento próximo, a maioria das codificações está associada a um conjunto de caracteres separado; Por exemplo, UTF-8,
Usado apenas para codificar conjuntos de caracteres Unicode. No entanto, é possível usar um esquema de codificação para lidar com vários conjuntos de caracteres. Por exemplo, o EUC pode codificar caracteres para vários idiomas asiáticos.
A Figura 6-1 é uma expressão gráfica que utiliza o esquema de codificação UTF-8 para codificar uma sequência de caracteres Unicode em uma sequência de bytes. UTF-8 codifica valores de código de caracteres menores que 0x80 em um valor de byte único (padrão ASC II). Todos os outros caracteres Unicode são codificados como sequências multibyte de 2 a 6 bytes (http://www.ietf.org/rfc/rfc2279.txt).
Conjunto de caracteres
O termo charset é definido em RFC2278 (http://ietf.org/rfc/rfc2278.txt). É uma coleção de conjuntos de caracteres codificados e esquemas de codificação de caracteres. A classe do pacote java.nio.charset é Charset, que encapsula a extração do conjunto de caracteres.
1111111111111111
Unicode é uma codificação de caracteres de 16 bits. Ele tenta unificar os conjuntos de caracteres de todas as línguas do mundo em um mapeamento único e abrangente. Ela conquistou seu lugar, mas existem muitas outras codificações de caracteres amplamente utilizadas atualmente.
A maioria dos sistemas operacionais ainda são orientados a bytes em termos de E/S e armazenamento de arquivos, portanto, independentemente da codificação usada, Unicode ou outras codificações, ainda há necessidade de conversão entre sequências de bytes e codificações de conjuntos de caracteres.
As classes compostas pelo pacote java.nio.charset atendem a essa necessidade. Esta não é a primeira vez que a plataforma Java lida com codificação de conjuntos de caracteres, mas é a solução mais sistemática, abrangente e flexível. O pacote java.nio.charset.spi fornece uma Interface de Provisionamento de Servidor (SPI) para que codificadores e decodificadores possam ser conectados conforme necessário.
Conjunto de caracteres: O valor padrão é determinado na inicialização da JVM e depende do ambiente do sistema operacional subjacente, do código do idioma e/ou da configuração da JVM. Se você precisar de um conjunto de caracteres específico, a aposta mais segura é nomeá-lo explicitamente. Não presuma que a implantação padrão é igual ao seu ambiente de desenvolvimento. Os nomes dos conjuntos de caracteres não diferenciam maiúsculas de minúsculas, ou seja, letras maiúsculas e minúsculas são consideradas iguais ao comparar nomes de conjuntos de caracteres. A Internet Assigned Names Authority (IANA) mantém todos os nomes de conjuntos de caracteres oficialmente registrados.
O Exemplo 6-1 demonstra como traduzir caracteres em sequências de bytes usando diferentes implementações de Charset.
Exemplo 6-1 Usando codificação de conjunto de caracteres padrão.
pacote com.ronsoft.books.nio.charset;
importar java.nio.charset.Charset;
importar java.nio.ByteBuffer;
/**
* Teste de codificação Charset Execute a mesma string de entrada, que contém alguns.
* caracteres não-ascii, através de vários codificadores Charset e despejar o hexadecimal
* valores das sequências de bytes resultantes.
*
* @autor Ron Hitchens ([email protected])
*/
classe pública EncodeTest {
public static void main(String[] argv) lança exceção {
//Esta é a sequência de caracteres a ser codificada
String entrada = "/u00bfMa/u00f1ana?";
//a lista de charsets para codificar
String[] charsetNames = { "US-ASCII", "ISO-8859-1", "UTF-8",
"UTF-16BE", "UTF-16LE", "UTF-16" // , "X-ROT13"
};
for (int i = 0; i < charsetNames.length; i++) {
doEncode(Charset.forName(charsetNames[i]), entrada);
}
}
/**
* Para um determinado Charset e string de entrada, codifique os caracteres e imprima o
* codificação de bytes resultante em formato legível.
*/
private static void doEncode(Charset cs, String input) {
ByteBuffer bb = cs.encode(entrada);
System.out.println("Conjunto de caracteres: " + cs.name());
System.out.println("Entrada:" + entrada);
System.out.println("Codificado: ");
for (int i = 0; bb.hasRemaining(); i++) {
int b = bb.get();
int ival = ((int) b) & 0xff;
char c = (char)ival;
//Mantém o alinhamento tabular bonito
se (eu <10)
System.out.print(" ");
//Imprime o número do índice
System.out.print(" " + i + ": ");
// Uma saída melhor formatada chegará algum dia...
se (ival <16)
System.out.print("0");
// Imprime o valor hexadecimal do byte
System.out.print(Integer.toHexString(ival));
// Se o byte parece ser o valor de um
// caractere imprimível, imprima-o.
// será.
if (Character.isWhitespace(c) || Character.isISOControl(c)) {
System.out.println("");
} outro {
System.out.println(" (" + c + ")");
}
}
System.out.println("");
}
}
Conjunto de caracteres: ISO-8859-1
Entrada: ?Ma?ana?
Codificado:
0:20
1: namorado (?)
2: 4d (M)
3:61(a)
4: f1 (?)
5:61(a)
6: 6e(n)
7:61(a)
8: 3f (?)
Conjunto de caracteres: UTF-8
Entrada: ?Ma?ana?
Codificado:
0:20
1: c2 (?)
2: namorado (?)
3: 4d (M)
4:61(a)
5: c3 (?)
6: b1 (±)
7:61(a)
8: 6e(n)
9:61(a)
10:3f (?)
Conjunto de caracteres: UTF-16BE
Entrada: ?Ma?ana?
Codificado:
0:00
1:20
14:00
3: namorado (?)
16:00
5: 4d (M)
6:00
7:61(a)
8:00
9: f1 (?)
10:00
11:61(a)
12:00
13: 6e(n)
14:00
15: 61 (a)
16:00
17:3f (?)
Conjunto de caracteres: UTF-16LE
Entrada: ?Ma?ana?
Codificado:
0:20
13:00
2: namorado (?)
3:00
4: 4d (M)
5:00
6:61(a)
7:00
8: f1 (?)
9:00
10:61(a)
11:00
12: 6e(n)
13:00
14: 61 (a)
15:00
16:3f(?)
17:00
Conjunto de caracteres: UTF-16
Entrada: ?Ma?ana?
Codificado:
0: fe (?)
1: ff (?)
14:00
3:20
16:00
5: namorado (?)
6:00
7: 4d (M)
8:00
9:61(a)
10:00
11: f1 (?)
12:00
13: 61 (a)
14:00
15: 6e(n)
16:00
17: 61 (a)
18:00
19:3f (?)
pacote java.nio.charset;
classe abstrata pública Charset implementa Comparable
{
público estático booleano isSupported (String charsetName)
Conjunto de caracteres estático público forName (String charsetName)
SortedMap estático público disponívelCharsets()
nome da string final pública()
final público Definir aliases()
String pública displayName()
public String displayName (localidade local)
público final booleano isRegistered()
canEncode booleano público()
público abstrato CharsetEncoder newEncoder();
Codificação ByteBuffer final pública (CharBuffer cb)
Codificação ByteBuffer final pública (String str)
público abstrato CharsetDecoder newDecoder();
decodificação CharBuffer final pública (ByteBuffer bb)
público abstrato booleano contém (Charset cs);
público final booleano igual (objeto ob)
público final int compareTo (objeto ob)
público final int hashCode()
String final pública paraString()
}
Na maioria das vezes, apenas os vendedores de JVM prestam atenção a essas regras. Entretanto, se você planeja usar seu próprio conjunto de caracteres como parte de seu aplicativo, será útil saber o que não fazer. Você deve retornar false para isRegistered() e nomear seu conjunto de caracteres começando com "X -".
Comparação do conjunto de caracteres:
classe abstrata pública Charset implementa Comparable
{
// Esta é uma listagem parcial da API
público abstrato booleano contém (Charset cs);
público final booleano igual (objeto ob)
público final int compareTo (objeto ob)
público final int hashCode()
String final pública paraString()
}
Codificador de conjunto de caracteres: Um conjunto de caracteres é composto por um conjunto de caracteres codificados e um esquema de codificação associado. As classes CharsetEncoder e CharsetDecoder implementam esquemas de conversão.
Uma observação sobre a API CharsetEncoder: primeiro, quanto mais simples o formulário encode(), mais conveniente ele é. A codificação do CharBuffer que você fornece no ByteBuffer realocado combina todas as codificações. Este é o último método chamado quando você chama encode() diretamente na classe Charset.
Subfluxo
Estouro
Entrada malformada
Personagem inmapeável
Durante a codificação, se o codificador encontrar uma entrada defeituosa ou não mapeável, um objeto de resultado será retornado. Você também pode testar caracteres individuais ou sequências de caracteres para determinar se eles podem ser codificados. Veja como verificar se a codificação é possível:
pacote java.nio.charset;
classe abstrata pública CharsetEncoder
{
// Esta é uma listagem parcial da API
canEncode booleano público (char c)
canEncode booleano público (CharSequence cs)
}
RELATÓRIO
Comportamento padrão ao criar um CharsetEncoder. Este comportamento indica que erros de codificação devem ser reportados retornando o objeto CoderResult, mencionado anteriormente.
IGNORAR (ignorar)
Indica que os erros de codificação devem ser ignorados e qualquer entrada incorreta deve ser abortada se estiver fora de posição.
SUBSTITUIR
Os erros de codificação são tratados abortando a entrada do erro e gerando a sequência de bytes de substituição atual definida para este CharsetEncoder.
Lembre-se de que a codificação do conjunto de caracteres converte caracteres em uma sequência de bytes em preparação para decodificação posterior. Se a sequência de substituição não puder ser decodificada em uma sequência de caracteres válida, a sequência de bytes codificados se tornará inválida.
Classe CoderResult: os objetos CoderResult são retornados pelos objetos CharsetEncoder e CharsetDecoder:
pacote java.nio.charset;
classe pública CoderResult {
público estático final CoderResult OVERFLOW
público estático final CoderResult UNDERFLOW
booleano público isUnderflow()
booleano público isOverflow()
<span style="white-space:pre"> </span>public boolean isError()
booleano público isMalformed()
booleano público isUnmappable()
comprimento interno público()
público estático CoderResult malformadoForLength (comprimento interno)
público estático CoderResult unmappableForLength (comprimento interno)
<span style="white-space:pre"> </span>public void throwException() lança CharacterCodingException
}
pacote java.nio.charset;
classe abstrata pública CharsetDecoder
{
// Esta é uma listagem parcial da API
redefinição final pública do CharsetDecoder()
decodificação CharBuffer final pública (ByteBuffer in)
lança CharacterCodingException
decodificação CoderResult final pública (ByteBuffer in, CharBuffer out,
booleano endOfInput)
liberação final pública do CoderResult (saída CharBuffer)
}
1. Reinicialize o decodificador chamando reset() para colocar o decodificador em um estado conhecido, pronto para receber entrada.
2. Defina endOfInput como false e não chame ou chame decode() várias vezes para fornecer bytes ao mecanismo de decodificação. À medida que a decodificação prossegue, caracteres serão adicionados ao CharBuffer fornecido.
3. Defina endOfInput como true e chame decode() uma vez para notificar o decodificador de que todas as entradas foram fornecidas.
4. Chame flush() para garantir que todos os caracteres decodificados foram enviados para a saída.
O Exemplo 6-2 ilustra como codificar um fluxo de bytes que representa uma codificação de conjunto de caracteres.
Exemplo 6-2. Decodificação do conjunto de caracteres.
pacote com.ronsoft.books.nio.charset;
importar java.nio.*;
importar java.nio.charset.*;
importar java.nio.channels.*;
importar java.io.*;
/**
* Teste a decodificação do conjunto de caracteres.
*
* @autor Ron Hitchens ([email protected])
*/
classe pública CharsetDecode {
/**
* Teste a decodificação do conjunto de caracteres no caso geral, detectando e manipulando buffer
* under/overflow e liberando o estado do decodificador no final da entrada Este código.
* lê stdin e decodifica o fluxo de bytes codificados em ASCII para chars.
* caracteres decodificados são gravados em stdout. Este é efetivamente um 'gato' para.
* insira arquivos ascii, mas outra codificação de conjunto de caracteres pode ser usada simplesmente
* especificando-o na linha de comando.
*/
public static void main(String[] argv) lança IOException {
// O conjunto de caracteres padrão é ASCII padrão
String charsetName = "ISO-8859-1";
// O nome do conjunto de caracteres pode ser especificado na linha de comando
if (comprimento do argumento > 0) {
charsetNome = argv[0];
}
// Envolve um canal em torno de stdin, envolve um canal em torno de stdout,
// encontre o Charset nomeado e passe-o para o método deco de.
// Se o charset nomeado não for válido, uma exceção do tipo
// UnsupportedCharsetException será lançada.
decodeChannel(Canais.newChannel(System.in), novo OutputStreamWriter(
System.out), Charset.forName(charsetName));
}
/**
* Método estático de uso geral que lê bytes de um canal, decodifica
*eles de acordo
*
* @param fonte
* Um objeto ReadableByteChannel que será lido para EOF como um
* fonte de bytes codificados.
* @param escritor
* Um objeto Writer no qual os caracteres decodificados serão gravados.
* @param conjunto de caracteres
* Um objeto Charset, cujo CharsetDecoder será utilizado para fazer o
* decodificação de conjunto de caracteres Java NIO 206.
*/
public static void decodeChannel (fonte ReadableByteChannel, gravador Writer,
Charset charset) lança UnsupportedCharsetException, IOException {
// Obtém uma instância do decodificador do Charset
decodificador CharsetDecoder = charset.newDecoder();
// Diz ao decodificador para substituir caracteres ruins pela marca padrão
decoder.onMalformedInput(CodingErrorAction.REPLACE);
decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
// Aloca tamanhos de buffer de entrada e saída radicalmente diferentes
//para fins de teste
ByteBuffer bb = ByteBuffer.allocateDirect(16 * 1024);
CharBuffer cb = CharBuffer.allocate(57);
// O buffer começa vazio; indica que a entrada é necessária;
Resultado CoderResult = CoderResult.UNDERFLOW;
booleano eof = falso;
enquanto (!eof) {
// Underflow do buffer de entrada; o decodificador deseja mais entrada;
if (resultado == CoderResult.UNDERFLOW) {
// o decodificador consome toda a entrada, prepare-se para recarregar
bb.claro();
// Preenche o buffer de entrada; observe EOF
eof = (source.read(bb) == -1);
//Prepara o buffer para leitura pelo decodificador
bb.flip();
}
//Decodifica bytes de entrada para caracteres de saída; passa flag EOF
resultado = decodificador.decode(bb, cb, eof);
//Se o buffer de saída estiver cheio, drena a saída
if (resultado == CoderResult.OVERFLOW) {
drenaCharBuf(cb, escritor);
}
}
//Libera qualquer estado restante do decodificador, tomando cuidado
//para detectar estouro(s) de buffer de saída
enquanto (decoder.flush(cb) == CoderResult.OVERFLOW) {
drenaCharBuf(cb, escritor);
}
//Drena todos os caracteres restantes no buffer de saída
drenaCharBuf(cb, escritor);
// Fecha o canal; envia todos os dados armazenados em buffer para stdout
fonte.close();
escritor.flush();
}
/**
* Método auxiliar para drenar o buffer de caracteres e gravar seu conteúdo no determinado
* Objeto Writer Ao retornar, o buffer está vazio e pronto para ser recarregado.
*
* @param cb
* Um CharBuffer contendo caracteres a serem gravados.
* @param escritor
* Um objeto Writer para consumir os caracteres em cb.
*/
static void drenaCharBuf (CharBuffer cb, escritor Writer) lança IOException {
cb.flip(); // Prepara buffer para drenagem
// Isso grava os caracteres contidos no CharBuffer, mas
// na verdade não modifica o estado do buffer.
// Se o buffer char estava sendo drenado por chamadas para get( ),
// um loop pode ser necessário aqui.
if (cb.hasRemaining()) {
escritor.write(cb.toString());
}
cb.clear(); // Prepara o buffer para ser preenchido novamente
}
}
Antes de navegar pela API, é importante explicar como funciona o Charset SPI. O pacote java.nio.charset.spi contém apenas uma classe de extração, CharsetProvider. Implementações concretas desta classe fornecem informações relacionadas aos objetos Charset que fornecem. Para definir um conjunto de caracteres customizado, você deve primeiro criar implementações específicas de Charset, CharsetEncoder e CharsetDecoder do pacote java.nio.charset. Em seguida, você cria uma subclasse customizada de CharsetProvider que fornecerá essas classes à JVM.
Crie um conjunto de caracteres personalizado:
O mínimo que você precisa fazer é criar uma subclasse de java.nio.charset.Charset, fornecer implementações concretas dos três métodos de extração e um construtor. A classe Charset não possui construtor padrão sem parâmetros. Isso significa que sua classe de conjunto de caracteres personalizado deve ter um construtor, mesmo que não aceite parâmetros. Isso ocorre porque você deve chamar o construtor do Charset no momento da instanciação (chamando super() no início do seu construtor), fornecendo-lhe assim o nome e o alias da especificação do charset. Fazer isso permite que os métodos da classe Charset lidem com as coisas relacionadas ao nome para você, então isso é uma coisa boa.
Da mesma forma, você precisa fornecer implementações concretas de CharsetEncoder e CharsetDecoder. Lembre-se de que um conjunto de caracteres é uma coleção de caracteres codificados e esquemas de codificação/decodificação. Como vimos antes, a codificação e a decodificação são quase simétricas no nível da API. Uma breve discussão sobre o que é necessário para implementar um codificador é apresentada aqui: o mesmo se aplica à construção de um decodificador.
Semelhante ao Charset, CharsetEncoder não possui um construtor padrão, então você precisa chamar super() no construtor da classe concreta, fornecendo os parâmetros necessários.
Para fornecer sua própria implementação CharsetEncoder, você deve fornecer pelo menos o método concreto encodeLoop (). Para algoritmos de codificação simples, a implementação padrão de outros métodos deve funcionar bem. Observe que encodeLoop() usa parâmetros semelhantes aos de encode(), excluindo o sinalizador booleano. O método encode () representa a codificação real para encodeLoop(), que só precisa prestar atenção aos caracteres consumidos do parâmetro CharBuffer e gerar os bytes codificados para o ByteBuffer fornecido.
Agora que vimos como implementar conjuntos de caracteres personalizados, incluindo os codificadores e decodificadores associados, vamos ver como conectá-los à JVM para que possamos executar código usando-os.
Forneça seu conjunto de caracteres personalizado:
Para fornecer sua própria implementação de Charset para o ambiente de tempo de execução JVM, você deve criar subclasses concretas da classe CharsetProvider em java.nio.charsets.-spi, cada uma com um construtor sem parâmetros. O construtor sem parâmetros é importante porque sua classe CharsetProvider será localizada lendo o nome completo do arquivo de configuração. Essa string de nome de classe será então importada para Class.newInstance() para instanciar seu provedor, que só funciona por meio do construtor sem parâmetros.
O arquivo de configuração lido pela JVM localiza o provedor do conjunto de caracteres, denominado java.nio.charset.spi.CharsetProvider. Ele está localizado no diretório de origem (META-INF/services) no classpath da JVM. Cada JavaArchive (JAR) possui um diretório META-INF que contém informações sobre as classes e recursos desse JAR. Um diretório chamado META-INF também pode ser colocado no topo dos diretórios regulares no caminho de classe da JVM.
A API CharsetProvider é quase inútil. O trabalho real de fornecer um conjunto de caracteres personalizado ocorre na criação de classes Charset, CharsetEncoder e CharsetDecoder personalizadas. O CharsetProvider é simplesmente um facilitador entre o seu conjunto de caracteres e o ambiente de execução.
O Exemplo 6-3 demonstra a implementação de um Charset e CharsetProvider personalizados, incluindo código de amostra que ilustra o uso, codificação e decodificação do conjunto de caracteres e o Charset SPI. O Exemplo 6-3 implementa um Charset personalizado.
Exemplo 6-3. Conjunto de caracteres Rot13 personalizado.
pacote com.ronsoft.books.nio.charset;
importar java.nio.CharBuffer;
importar java.nio.ByteBuffer;
importar java.nio.charset.Charset;
importar java.nio.charset.CharsetEncoder;
importar java.nio.charset.CharsetDecoder;
importar java.nio.charset.CoderResult;
importar java.util.Map;
importar java.util.Iterator;
importar java.io.Writer;
importar java.io.PrintStream;
importar java.io.PrintWriter;
importar java.io.OutputStreamWriter;
importar java.io.BufferedReader;
importar java.io.InputStreamReader;
importar java.io.FileReader;
/**
* Uma implementação Charset que executa a codificação Rot13 é uma codificação.
* algoritmo de ofuscação de texto simples que muda os caracteres alfabéticos em 13
* para que 'a' se torne 'n', 'o' se torne 'b', etc. Este algoritmo foi popularizado
* pelos fóruns de discussão da Usenet há muitos anos para mascarar palavrões, esconder
* respostas a perguntas e assim por diante O algoritmo Rot13 é simétrico, aplicando-se.
* para o texto que foi embaralhado pelo Rot13 lhe dará o original
* texto não embaralhado.
*
* Aplicar esta codificação Charset a um fluxo de saída fará com que tudo que você
* escreva para esse fluxo para que o Rot13 seja embaralhado conforme for escrito.
* para um fluxo de entrada faz com que os dados lidos sejam descodificados em Rot13 à medida que são lidos.
*
* @autor Ron Hitchens ([email protected])
*/
classe pública Rot13Charset estende Charset {
// o nome da codificação base do conjunto de caracteres à qual delegamos
final estático privado String BASE_CHARSET_NAME = "UTF-8";
// Identifica o conjunto de caracteres real que usaremos para transcodificação entre
// caracteres e bytes. Fazer isso nos permite aplicar o Rot13.
// algoritmo para codificações de conjuntos de caracteres multibyte.
// Os caracteres alfa ASCII serão rotacionados, independentemente da codificação base.
Conjunto de caracteres baseCharset;
/**
* Construtor para o conjunto de caracteres Rot13 Chame o construtor da superclasse para.
* passe adiante o(s) nome(s) pelos quais seremos conhecidos. Em seguida, salve uma referência ao(s) nome(s).
* delegar Charset.
*/
protegido Rot13Charset(String canônico, String[] aliases) {
super(canônico, aliases);
// Salva o conjunto de caracteres base ao qual estamos delegando
baseCharset = Charset.forName(BASE_CHARSET_NAME);
}
//------------------------------------------------ ----------
/**
* Chamado pelos usuários deste Charset para obter um codificador desta implementação.
* instancia uma instância de uma classe privada (definida abaixo) e a passa
* um codificador do Charset base.
*/
public CharsetEncoder newEncoder() {
retornar novo Rot13Encoder(this, baseCharset.newEncoder());
}
/**
* Chamado pelos usuários deste Charset para obter um decodificador desta implementação.
* instancia uma instância de uma classe privada (definida abaixo) e a passa
* um decodificador do Charset base.
*/
public CharsetDecoder newDecoder() {
retornar novo Rot13Decoder(this, baseCharset.newDecoder());
}
/**
* Este método deve ser implementado por Charsets concretos. Sempre dizemos não,
* o que é seguro.
*/
booleano público contém(Charset cs) {
retornar (falso);
}
/**
* Rotina comum para girar todos os caracteres alfa ASCII no dado
* CharBuffer por 13. Observe que este código compara explicitamente para superior e
* caracteres ASCII minúsculos em vez de usar os métodos
* Character.isLowerCase e Character.isUpperCase Isso ocorre porque o.
* O esquema de rotação por 13 só funciona corretamente para os caracteres alfabéticos de
* o conjunto de caracteres ASCII e esses métodos podem retornar verdadeiro para Unicode não-ASCII
* caracteres.
*/
privado void rot13(CharBuffer cb) {
for (int pos = cb.posição(); pos < cb.limit(); pos++) {
char c = cb.get(pos);
char a = '/u0000';
//É alfa minúsculo?
if ((c >= 'a') && (c <= 'z')) {
uma = 'uma';
}
//É alfa maiúsculo?
if ((c >= 'A') && (c <= 'Z')) {
uma = 'A';
}
// Se sim, role por 13
if (a != '/u0000') {
c = (char) ((((c - a) + 13) % 26) + a);
cb.put(pos, c);
}
}
}
//------------------------------------------------ --------
/**
* A implementação do codificador para Rot13 Chars et.
* classe de decodificador correspondente abaixo, também deve substituir os métodos "impl",
* como implOnMalformedInput( ) e fazer chamadas de passagem para o
* objeto baseEncoder Isso é deixado como exercício para o hacker.
*/
classe privada Rot13Encoder estende CharsetEncoder {
private CharsetEncoder baseEncoder;
/**
* Construtor, chame o construtor da superclasse com o objeto Charset
* e os tamanhos de codificação do codificador delegado.
*/
Rot13Encoder(Charset cs, CharsetEncoder baseEncoder) {
super (cs, baseEncoder.averageBytesPerChar(), baseEncoder
.maxBytesPerChar());
this.baseEncoder = baseEncoder;
}
/**
* Implementação do loop de codificação Primeiro, aplicamos o Rot13.
* algoritmo de embaralhamento para o CharBuffer e, em seguida, redefina o codificador para
* o Charset base e chame seu método encode() para fazer o real
* codificação. Isso pode não funcionar corretamente para conjuntos de caracteres não latinos.
* CharBuffer passado pode ser somente leitura ou reutilizado pelo chamador para
* outros fins, então duplicamos e aplicamos a codificação Rot13 ao
* copiar. Queremos avançar a posição do buffer de entrada para.
* reflete os caracteres consumidos.
*/
protegido CoderResult encodeLoop(CharBuffer cb, ByteBuffer bb) {
CharBuffer tmpcb = CharBuffer.allocate(cb.remaining());
enquanto (cb.hasRemaining()) {
tmpcb.put(cb.get());
}
tmpcb.rewind();
rot13(tmpcb);
baseEncoder.reset();
CoderResult cr = baseEncoder.encode(tmpcb, bb, true);
// Se houver erro ou estouro de saída, precisamos ajustar
// a posição do buffer de entrada para corresponder ao que
// foi realmente consumido do buffer temporário If.
// underflow (todas as entradas consumidas), este é um ambiente autônomo.
cb.posição(cb.posição() - tmpcb.remaining());
retorno(cr);
}
}
//------------------------------------------------ --------
/**
* A implementação do decodificador para o Rot13 Charset.
*/
classe privada Rot13Decoder estende CharsetDecoder {
charsetDecoder privado baseDecoder;
/**
* Construtor, chame o construtor da superclasse com o objeto Charset
* e passe adiante os valores de caracteres/byte do decodificador delegado.
*/
Rot13Decoder(Charset cs, CharsetDecoder baseDecoder) {
super(cs, baseDecoder.averageCharsPerByte(), baseDecoder
.maxCharsPerByte());
this.baseDecoder = baseDecoder;
}
/**
* Implementação do loop de decodificação Primeiro, reinicializamos o decodificador.
* o conjunto de caracteres base e chame-o para decodificar os bytes em caracteres,
* salvando o código de resultado O CharBuffer é então descodificado com o.
* Algoritmo Rot13 e o código de resultado são retornados. Isso pode não funcionar.
* corretamente para conjuntos de caracteres não latinos.
*/
CoderResult protegido decodeLoop(ByteBuffer bb, CharBuffer cb) {
baseDecoder.reset();
CoderResult resultado = baseCoder.Decode (BB, CB, TRUE);
ROT13 (CB);
return (resultado);
}
}
// -------------------------------------------------- --------
/**
* Teste de unidade para o charset Rot13.
* Arquivo se nomeado na linha de comando, ou stdin se nenhum args for fornecido, e
* Escreva o conteúdo para Stdout através da codificação X -ROT13
* "Criptografia" implementada pelo algoritmo ROT13 é simétrico
* Em um arquivo de texto simples, como o código-fonte Java, por exemplo, será lançado um
* Versão embaralhada.
* documento de texto simples original.
*/
public static void main (string [] argv) lança exceção {
BufferredReader in;
if (argv. comprimento> 0) {
// Abra o arquivo nomeado
in = new bufferredreader (novo fileReader (argv [0]));
} outro {
// Enrole um leitor de buffers em torno de stdin
in = new bufferredreader (new InputStreamReader (System.in));
}
// Crie um PrintStream que use a codificação ROT13
PrintStream Out = new PrintStream (System.out, False, "X -Rot13");
String s = nulo;
// Leia toda a entrada e escreva na saída.
// À medida que os dados passam pela PrintStream,
// será codificado por ROT13.
while ((s = in.readline ())! = null) {
out.println (s);
}
fora.flush();
}
}
Exemplo 6-4.
pacote com.ronsoft.books.nio.charset;
importar java.nio.charset.charset;
importar java.nio.charset.spi.charsetProvider;
importar java.util.HashSet;
importar java.util.iterator;
/**
* Uma classe CharsetProvider que disponibiliza os charsets fornecidos por
* Atualmente
* Não é um Charset Iana registrado, então o nome começa com "X-" para evitar o nome
* confronta com charsets offical.
*
* Para ativar este CharsetProvider, é necessário adicionar um arquivo ao
* ClassPath of the JVM Runtime no seguinte local:
* Meta-inf/Services/java.nio.charsets.spi.charsetProvider
*
* Esse arquivo deve conter uma linha com o nome totalmente qualificado desta classe em
* Uma linha por si só: com.ronsoft.books.nio.charset.ronsoftcharsetProvider java
* NIO 216
*
* Veja a página javadoc para java.nio.charsets.spi.charsetProvider para completo
* detalhes.
*
* @Author Ron Hitchens ([email protected])
*/
classe pública ronsoftcharsetprovider estende o charsetprovider {
// o nome do charset que fornecemos
private estático final string charset_name = "x-rot13";
// uma alça para o objeto Charset
Rot13 do charset privado = nulo;
/**
* Construtor, instancie um objeto Charset e salve a referência.
*/
public ronsoftcharsetProvider () {
this.rot13 = novo Rot13Charset (charset_name, new string [0]);
}
/**
* Chamado por Métodos estáticos do CHARSET para encontrar um Charset nomeado específico
* é o nome deste charset (não temos nenhum apelido) e depois retornam o
* ROT13 CHARSET, CELE RETORNO NULL.
*/
public Charset CharsetForName (String charsetName) {
if (charsetName.equalsignorecase (charset_name)) {
retornar (ROT13);
}
retornar (nulo);
}
/**
* Retorne um iterador sobre o conjunto de objetos Charset que fornecemos.
*
* @return Um objeto iterador contendo referências a todo o charset
* Objetos fornecidos por esta classe.
*/
Public Iterator <Charset> charsets () {
Hashset <CharSet> set = new Hashset <CharSet> (1);
set.add (ROT13);
return (set.iterator ());
}
}
A adição de x -Rot13 à lista de conjuntos de caracteres no Exemplo 6-1 produz esta saída adicional:
CHARSET: X-ROT13
Entrada: żmaana?
Codificado:
0: C2 (ż)
1: BF (ż)
2: 5a (z)
3: 6e (n)
4: C3 (Ê)
5: B1 (±)
6: 6e (n)
7:61 (a)
8: 6e (n)
9: 3f (?)
Charset (classe de conjunto de caracteres)
Um esquema de codificação de conjunto de caracteres que encapsula a codificação usada para representar sequências de caracteres diferentes do conjunto de caracteres como uma sequência de bytes.
CHARSETENCODER (Classe de codificação do conjunto de caracteres)
A codificação do motor converte seqüências de caracteres em sequências de bytes. A sequência de bytes pode então ser decodificada para reconstruir a sequência do caractere de origem.
CharsetDecoder (classe de decodificador de charset)
O motor de decodificação converte a sequência de bytes codificada em uma sequência de caracteres.
CharsetProvider SPI (provedor de charset SPI)
Localize e disponibilize a implementação do charset através do mecanismo de fornecedor do servidor para uso no ambiente de tempo de execução.