Conceptos básicos del juego de caracteres:
conjunto de caracteres
Una colección de caracteres, es decir, símbolos con semántica especial. La letra "A" es un carácter. "%" también es un carácter. No tiene ningún valor numérico intrínseco y no tiene conexión directa con ASC II, Unicode o incluso con computadoras. Los símbolos existieron mucho antes que las computadoras.
Juego de caracteres codificados
Se asigna un valor numérico a una colección de caracteres. Asigne códigos a los caracteres para que puedan expresar resultados numéricos utilizando un conjunto de codificación de caracteres específico. Otros conjuntos de caracteres codificados pueden asignar valores diferentes al mismo carácter. Las asignaciones de juegos de caracteres suelen estar determinadas por organizaciones de estándares, como USASCII, ISO 8859-1, Unicode (ISO 10646-1) y JIS X0201.
Esquema de codificación de caracteres
Mapeo de miembros del juego de caracteres codificados a octetos (bytes de 8 bits). Un esquema de codificación define cómo se expresa una secuencia de codificaciones de caracteres como una secuencia de bytes. No es necesario que el valor de la codificación de caracteres sea el mismo que el byte de codificación, ni que sea una relación uno a uno o uno a muchos. En principio, la codificación y decodificación de juegos de caracteres se puede aproximar a la serialización y deserialización de objetos.
Por lo general, la codificación de datos de caracteres se utiliza para la transmisión de red o el almacenamiento de archivos. Un esquema de codificación no es un conjunto de caracteres, es una asignación, pero debido a su estrecha relación, la mayoría de las codificaciones están asociadas con un conjunto de caracteres independiente. Por ejemplo, UTF-8,
Sólo se utiliza para codificar conjuntos de caracteres Unicode. No obstante, es posible utilizar un esquema de codificación para manejar múltiples conjuntos de caracteres. Por ejemplo, EUC puede codificar caracteres para varios idiomas asiáticos.
La Figura 6-1 es una expresión gráfica que utiliza el esquema de codificación UTF-8 para codificar una secuencia de caracteres Unicode en una secuencia de bytes. UTF-8 codifica valores de código de caracteres inferiores a 0x80 en un valor de un solo byte (estándar ASC II). Todos los demás caracteres Unicode están codificados como secuencias multibyte de 2 a 6 bytes (http://www.ietf.org/rfc/rfc2279.txt).
conjunto de caracteres
El término juego de caracteres se define en RFC2278 (http://ietf.org/rfc/rfc2278.txt). Es una colección de conjuntos de caracteres codificados y esquemas de codificación de caracteres. La clase del paquete java.nio.charset es Charset, que encapsula la extracción del juego de caracteres.
1111111111111111
Unicode es una codificación de caracteres de 16 bits. Intenta unificar los conjuntos de caracteres de todos los idiomas del mundo en un mapeo único y completo. Se ha ganado su lugar, pero existen muchas otras codificaciones de caracteres de uso generalizado en la actualidad.
La mayoría de los sistemas operativos todavía están orientados a bytes en términos de E/S y almacenamiento de archivos, por lo que no importa qué codificación se utilice, Unicode u otras codificaciones, todavía existe la necesidad de convertir entre secuencias de bytes y codificaciones de conjuntos de caracteres.
Las clases compuestas por el paquete java.nio.charset satisfacen esta necesidad. Esta no es la primera vez que la plataforma Java se ocupa de la codificación de juegos de caracteres, pero es la solución más sistemática, completa y flexible. El paquete java.nio.charset.spi proporciona una interfaz de aprovisionamiento de servidor (SPI) para que se puedan conectar codificadores y decodificadores según sea necesario.
Conjunto de caracteres: el valor predeterminado se determina al iniciar JVM y depende del entorno del sistema operativo subyacente, la configuración regional y/o la configuración de JVM. Si necesita un conjunto de caracteres específico, lo más seguro es nombrarlo explícitamente. No asuma que la implementación predeterminada es la misma que la de su entorno de desarrollo. Los nombres de los juegos de caracteres no distinguen entre mayúsculas y minúsculas, es decir, las letras mayúsculas y minúsculas se consideran iguales al comparar los nombres de los juegos de caracteres. La Autoridad de Nombres Asignados en Internet (IANA) mantiene todos los nombres de conjuntos de caracteres registrados oficialmente.
El ejemplo 6-1 demuestra cómo traducir caracteres en secuencias de bytes utilizando diferentes implementaciones de Charset.
Ejemplo 6-1. Uso de codificación de juego de caracteres estándar.
paquete com.ronsoft.books.nio.charset;
importar java.nio.charset.Charset;
importar java.nio.ByteBuffer;
/**
* Prueba de codificación de caracteres. Ejecute la misma cadena de entrada, que contiene algo.
* caracteres no ASCII, a través de varios codificadores Charset y descartar el hexadecimal
* valores de las secuencias de bytes resultantes.
*
* @autor Ron Hitchens ([email protected])
*/
clase pública EncodeTest {
public static void main (String [] argv) lanza una excepción {
// Esta es la secuencia de caracteres a codificar
Entrada de cadena = "/u00bfMa/u00f1ana?";
// la lista de conjuntos de caracteres 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 un conjunto de caracteres y una cadena de entrada determinados, codifique los caracteres e imprima el
* codificación de bytes resultante en un formato legible.
*/
doEncode vacío estático privado (Charset cs, entrada de cadena) {
ByteBuffer bb = cs.encode(entrada);
System.out.println("Juego de caracteres: " + cs.name());
System.out.println(" Entrada: " + entrada);
System.out.println("Codificado: ");
para (int i = 0; bb.hasRemaining(); i++) {
int b = bb.get();
int ival = ((int) b) & 0xff;
char c = (char) ival;
// Mantener bonita la alineación tabular
si (yo < 10)
Sistema.out.print(" ");
//Imprimir número de índice
System.out.print(" " + i + ": ");
// Algún día llegará una salida mejor formateada...
si (val < 16)
System.out.print("0");
// Imprime el valor hexadecimal del byte
System.out.print(Integer.toHexString(ival));
// Si el byte parece ser el valor de un
// carácter imprimible, imprimirlo. No hay garantía.
// así será.
if (Character.isWhitespace(c) || Character.isISOControl(c)) {
System.out.println("");
} demás {
System.out.println(" (" + c + ")");
}
}
System.out.println("");
}
}
Juego de caracteres: ISO-8859-1
Entrada: ?Ma?ana?
Codificado:
0:20
1: novio (?)
2: 4d (M)
3:61(a)
4: f1 (?)
5:61(a)
6: 6e(n)
7:61(a)
8:3f (?)
Juego de caracteres: UTF-8
Entrada: ?Ma?ana?
Codificado:
0:20
1: c2 (?)
2: novio (?)
3: 4d (M)
4:61(a)
5: c3 (?)
6: b1 (±)
7:61(a)
8: 6e(n)
9:61(a)
10:3f (?)
Juego de caracteres: UTF-16BE
Entrada: ?Ma?ana?
Codificado:
0:00
1:20
2:00
3: novio (?)
4: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 (?)
Juego de caracteres: UTF-16LE
Entrada: ?Ma?ana?
Codificado:
0:20
1:00
2: novio (?)
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
Juego de caracteres: UTF-16
Entrada: ?Ma?ana?
Codificado:
0: fe (?)
1:ff (?)
2:00
3:20
4:00
5: novio (?)
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 (?)
paquete java.nio.charset;
clase abstracta pública Charset implementa Comparable
{
booleano estático público isSupported (String charsetName)
Juego de caracteres estático público para nombre (String charsetName)
SortedMap estático público disponibleCharsets()
nombre de cadena final pública()
público final Establecer alias()
cadena pública displayName()
cadena pública displayName (localización local)
público final booleano está registrado ()
canEncode booleano público()
resumen público CharsetEncoder newEncoder();
Codificación pública final de ByteBuffer (CharBuffer cb)
codificación ByteBuffer final pública (String str)
resumen público CharsetDecoder newDecoder();
Decodificación pública final de CharBuffer (ByteBuffer bb)
El booleano abstracto público contiene (Charset cs);
público final booleano es igual (Objeto ob)
public final int compareTo (Objeto ob)
código hash int final público ()
Cadena final pública toString()
}
La mayoría de las veces, sólo los vendedores de JVM prestan atención a estas reglas. Sin embargo, si planea utilizar su propio conjunto de caracteres como parte de su aplicación, será útil saber qué no hacer. Debe devolver falso para isRegistered() y nombrar su conjunto de caracteres comenzando con "X -".
Comparación de juegos de caracteres:
clase abstracta pública Charset implementa Comparable
{
// Este es un listado parcial de API
El booleano abstracto público contiene (Charset cs);
público final booleano es igual (Objeto ob)
public final int compareTo (Objeto ob)
código hash int final público ()
Cadena final pública toString()
}
Codificador de juego de caracteres: un juego de caracteres se compone de un juego de caracteres codificados y un esquema de codificación asociado. Las clases CharsetEncoder y CharsetDecoder implementan esquemas de conversión.
Una nota sobre la API CharsetEncoder: primero, cuanto más simple sea el formato encode(), más conveniente será. La codificación del CharBuffer que proporciona en el ByteBuffer reasignado combina todas las codificaciones. Este es el último método llamado cuando llamas a encode() directamente en la clase Charset.
Desbordamiento
Rebosar
Entrada mal formada
Carácter no mapeable
Durante la codificación, si el codificador encuentra una entrada defectuosa o no asignable, se devuelve un objeto de resultado. También puede probar caracteres individuales o secuencias de caracteres para determinar si se pueden codificar. A continuación se explica cómo comprobar si es posible la codificación:
paquete java.nio.charset;
clase abstracta pública CharsetEncoder
{
// Este es un listado parcial de API
canEncode booleano público (char c)
canEncode booleano público (CharSequence cs)
}
INFORME
Comportamiento predeterminado al crear un CharsetEncoder. Este comportamiento indica que los errores de codificación deben informarse devolviendo el objeto CoderResult, mencionado anteriormente.
IGNORAR (ignorar)
Indica que los errores de codificación deben ignorarse y cualquier entrada incorrecta debe cancelarse si está fuera de posición.
REEMPLAZAR
Los errores de codificación se manejan cancelando la entrada del error y generando la secuencia de bytes de reemplazo actual definida para este CharsetEncoder.
Recuerde, la codificación del juego de caracteres convierte los caracteres en una secuencia de bytes en preparación para su posterior decodificación. Si la secuencia de reemplazo no se puede decodificar en una secuencia de caracteres válida, la secuencia de bytes codificada deja de ser válida.
Clase CoderResult: los objetos CoderResult son devueltos por los objetos CharsetEncoder y CharsetDecoder:
paquete java.nio.charset;
clase pública CoderResult {
CoderResult final estático público DESBORDAMIENTO
CoderResult final estático público UNDERFLOW
booleano público esUnderflow()
booleano público isOverflow()
<span style="white-space:pre"> </span>público booleano isError()
booleano público está mal formado()
booleano público es inasignable()
longitud int pública()
CoderResult estático público malformadoForLength (longitud int)
CoderResult estático público unmappableForLength (longitud int)
<span style="white-space:pre"> </span>public void throwException() lanza CharacterCodingException
}
paquete java.nio.charset;
clase abstracta pública CharsetDecoder
{
// Este es un listado parcial de API
reinicio público final de CharsetDecoder()
Decodificación pública final de CharBuffer (ByteBuffer en)
lanza CharacterCodingException
Decodificación pública final de CoderResult (ByteBuffer entra, CharBuffer sale,
final booleano de entrada)
Descarga pública final de CoderResult (fuera CharBuffer)
}
1. Reinicie el decodificador llamando a reset() para poner el decodificador en un estado conocido, listo para recibir entradas.
2. Establezca endOfInput en falso y no llame ni llame a decode() varias veces para suministrar bytes al motor de decodificación. A medida que avanza la decodificación, se agregarán caracteres al CharBuffer dado.
3. Establezca endOfInput en verdadero y llame a decode() una vez para notificar al decodificador que se han proporcionado todas las entradas.
4. Llame a flush() para asegurarse de que todos los caracteres decodificados se hayan enviado a la salida.
El ejemplo 6-2 ilustra cómo codificar un flujo de bytes que representa una codificación de juego de caracteres.
Ejemplo 6-2. Decodificación de juegos de caracteres.
paquete com.ronsoft.books.nio.charset;
importar java.nio.*;
importar java.nio.charset.*;
importar java.nio.channels.*;
importar java.io.*;
/**
* Pruebe la decodificación del juego de caracteres.
*
* @autor Ron Hitchens ([email protected])
*/
clase pública CharsetDecode {
/**
* Pruebe la decodificación del juego de caracteres en el caso general, detectando y manejando el búfer
* sub/desbordamiento y vaciado del estado del decodificador al final de la entrada de este código.
* lee desde stdin y decodifica el flujo de bytes codificado en ASCII en caracteres.
* Los caracteres decodificados se escriben en la salida estándar. Esto es efectivamente un 'gato' para.
* Ingrese archivos ASCII, pero se podría usar otra codificación de juego de caracteres simplemente
*especificándolo en la línea de comando.
*/
public static void main(String[] argv) lanza IOException {
// El juego de caracteres predeterminado es ASCII estándar
Cadena nombre_charset = "ISO-8859-1";
// El nombre del juego de caracteres se puede especificar en la línea de comando
si (argv. longitud > 0) {
nombrejuegochars = argv[0];
}
// Envuelve un canal alrededor de la entrada estándar, envuelve un canal alrededor de la salida estándar,
// busca el Charset nombrado y lo pasa al método deco de.
// Si el juego de caracteres nombrado no es válido, se produce una excepción de tipo
// Se lanzará una excepción UnsupportedCharsetException.
decodeChannel(Channels.newChannel(System.in), nuevo OutputStreamWriter(
System.out), Charset.forName(charsetName));
}
/**
* Método estático de propósito general que lee bytes de un canal, decodifica
* ellos según
*
* @param fuente
* Un objeto ReadableByteChannel que se leerá en EOF como un
* fuente de bytes codificados.
* @param escritor
* Un objeto Writer en el que se escribirán los caracteres decodificados.
* @param juego de caracteres
* Un objeto Charset, cuyo CharsetDecoder se utilizará para hacer el
* decodificación del juego de caracteres Java NIO 206.
*/
decodeChannel vacío estático público (fuente ReadableByteChannel, escritor,
Charset charset) arroja UnsupportedCharsetException, IOException {
// Obtener una instancia de decodificador del Charset
Decodificador CharsetDecoder = charset.newDecoder();
// Dile al decodificador que reemplace los caracteres incorrectos con la marca predeterminada
decodificador.onMalformedInput(CodingErrorAction.REPLACE);
decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
// Asigna tamaños de buffer de entrada y salida radicalmente diferentes
// para fines de prueba
ByteBuffer bb = ByteBuffer.allocateDirect(16 * 1024);
CharBuffer cb = CharBuffer.allocate(57);
// El búfer comienza vacío; indica que se necesita entrada
Resultado de CoderResult = CoderResult.UNDERFLOW;
booleano eof = falso;
mientras (!eof) {
// Desbordamiento insuficiente del búfer de entrada; el decodificador quiere más entradas;
si (resultado == CoderResult.UNDERFLOW) {
// el decodificador consume toda la entrada, prepárese para recargar
bb.clear();
// Llene el búfer de entrada y busque EOF;
eof = (fuente.read(bb) == -1);
//Preparar el buffer para lectura por decodificador
bb.flip();
}
// Decodifica bytes de entrada para generar caracteres; pasa el indicador EOF;
resultado = decodificador.decodificar(bb, cb, eof);
// Si el buffer de salida está lleno, drena la salida
si (resultado == CoderResult.OVERFLOW) {
drenajeCharBuf(cb, escritor);
}
}
// Elimina cualquier estado restante del decodificador, teniendo cuidado
// para detectar desbordamientos del buffer de salida
mientras (decoder.flush(cb) == CoderResult.OVERFLOW) {
drenajeCharBuf(cb, escritor);
}
// Drena los caracteres restantes en el buffer de salida
drenajeCharBuf(cb, escritor);
// Cerrar el canal; enviar todos los datos almacenados en el búfer a la salida estándar.
fuente.close();
escritor.flush();
}
/**
* Método auxiliar para drenar el búfer de caracteres y escribir su contenido en el dado
* Objeto de escritura Al regresar, el búfer está vacío y listo para ser rellenado.
*
* @param cb
* Un CharBuffer que contiene caracteres para escribir.
* @param escritor
* Un objeto Writer para consumir los caracteres en cb.
*/
drenaje vacío estáticoCharBuf (CharBuffer cb, escritor escritor) lanza IOException {
cb.flip(); // Preparar el búfer para drenar
// Esto escribe los caracteres contenidos en CharBuffer pero
// en realidad no modifica el estado del búfer.
// Si las llamadas a get() estaban agotando el buffer de caracteres,
// puede que sea necesario un bucle aquí.
si (cb.hasRemaining()) {
escritor.write(cb.toString());
}
cb.clear(); // Prepara el buffer para llenarlo nuevamente
}
}
Antes de explorar la API, es importante explicar cómo funciona Charset SPI. El paquete java.nio.charset.spi contiene solo una clase de extracción, CharsetProvider. Las implementaciones concretas de esta clase proporcionan información relacionada con los objetos Charset que proporcionan. Para definir un juego de caracteres personalizado, primero debe crear implementaciones específicas de Charset, CharsetEncoder y CharsetDecoder a partir del paquete java.nio.charset. Luego crea una subclase personalizada de CharsetProvider que proporcionará esas clases a la JVM.
Crea un juego de caracteres personalizado:
Lo mínimo que tienes que hacer es crear una subclase de java.nio.charset.Charset, proporcionar implementaciones concretas de los tres métodos de extracción y un constructor. La clase Charset no tiene un constructor predeterminado sin parámetros. Esto significa que su clase de juego de caracteres personalizado debe tener un constructor, incluso si no acepta parámetros. Esto se debe a que debe llamar al constructor de Charset en el momento de la creación de instancias (llamando a super() al comienzo de su constructor), proporcionándole así el nombre y alias de su especificación de charset. Hacer esto permite que los métodos de la clase Charset manejen las cosas relacionadas con el nombre por usted, así que eso es algo bueno.
Asimismo, debe proporcionar implementaciones concretas de CharsetEncoder y CharsetDecoder. Recuerde que un juego de caracteres es una colección de caracteres codificados y esquemas de codificación/decodificación. Como vimos antes, la codificación y decodificación son casi simétricas a nivel de API. Aquí se ofrece una breve discusión de lo que se necesita para implementar un codificador: lo mismo se aplica a la construcción de un decodificador.
Al igual que Charset, CharsetEncoder no tiene un constructor predeterminado, por lo que debe llamar a super() en el constructor de la clase concreta, proporcionando los parámetros requeridos.
Para proporcionar su propia implementación de CharsetEncoder, debe al menos proporcionar el método encodeLoop () concreto. Para algoritmos de codificación simples, la implementación predeterminada de otros métodos debería funcionar bien. Tenga en cuenta que encodeLoop() toma parámetros similares a los de encode(), excluyendo el indicador booleano. El método encode () representa la codificación real para encodeLoop (), que solo necesita prestar atención a los caracteres consumidos del parámetro CharBuffer y enviar los bytes codificados al ByteBuffer proporcionado.
Ahora que hemos visto cómo implementar conjuntos de caracteres personalizados, incluidos los codificadores y decodificadores asociados, veamos cómo conectarlos a la JVM para que podamos ejecutar código usándolos.
Proporcione su conjunto de caracteres personalizado:
Para proporcionar su propia implementación de Charset al entorno de ejecución de JVM, debe crear subclases concretas de la clase CharsetProvider en java.nio.charsets.-spi, cada una con un constructor sin parámetros. El constructor sin parámetros es importante porque su clase CharsetProvider se ubicará leyendo el nombre completo del archivo de configuración. Esta cadena de nombre de clase luego se importará a Class.newInstance() para crear una instancia de su proveedor, que solo funciona a través del constructor sin parámetros.
El archivo de configuración leído por la JVM localiza el proveedor del juego de caracteres, que se denomina java.nio.charset.spi.CharsetProvider. Se encuentra en el directorio fuente (META-INF/services) en la ruta de clases de JVM. Cada JavaArchive (JAR) tiene un directorio META-INF que contiene información sobre las clases y recursos en ese JAR. También se puede colocar un directorio llamado META-INF en la parte superior de los directorios normales en el classpath de JVM.
La API CharsetProvider es casi inútil. El trabajo real de proporcionar un juego de caracteres personalizado se produce al crear clases personalizadas Charset, CharsetEncoder y CharsetDecoder. CharsetProvider es simplemente un facilitador entre su conjunto de caracteres y el entorno de ejecución.
El ejemplo 6-3 demuestra la implementación de un Charset y CharsetProvider personalizados, incluido un código de muestra que ilustra el uso, codificación y decodificación del juego de caracteres, y el Charset SPI. El ejemplo 6-3 implementa un juego de caracteres personalizado.
Ejemplo 6-3. Conjunto de caracteres Rot13 personalizado.
paquete 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;
/**
* Una implementación Charset que realiza la codificación Rot13 es una.
* algoritmo de ofuscación de texto simple que cambia los caracteres alfabéticos en 13
* para que 'a' se convierta en 'n', 'o' se convierta en 'b', etc. Este algoritmo se popularizó
* por los foros de discusión de Usenet hace muchos años para enmascarar palabras obscenas, ocultar
* respuestas a preguntas, etc. El algoritmo Rot13 es simétrico y se aplica.
* el texto codificado por Rot13 le dará el original
* texto descifrado.
*
* Aplicar esta codificación Charset a un flujo de salida hará que todo lo que
* escribir en esa secuencia para que se codifique en Rot13 a medida que se escribe y se aplica.
* a un flujo de entrada hace que los datos leídos se descifren en Rot13 a medida que se leen.
*
* @autor Ron Hitchens ([email protected])
*/
clase pública Rot13Charset extiende Charset {
// el nombre de la codificación del juego de caracteres base a la que delegamos
Cadena final estática privada BASE_CHARSET_NAME = "UTF-8";
// Maneja el conjunto de caracteres real que usaremos para la transcodificación entre
// caracteres y bytes Hacer esto nos permite aplicar el Rot13.
// algoritmo para codificaciones de conjuntos de caracteres multibyte. Pero solo el
// Los caracteres alfa ASCII se rotarán, independientemente de la codificación base.
Juego de caracteres baseCharset;
/**
* Constructor para el conjunto de caracteres Rot13 Llame al constructor de la superclase.
* pasar los nombres por los que seremos conocidos. Luego guardar una referencia al.
* delegado Charset.
*/
protected Rot13Charset (String canonical, String [] alias) {
super(canónico, alias);
// Guarda el juego de caracteres base al que estamos delegando
baseCharset = Charset.forName(BASE_CHARSET_NAME);
}
//------------------------------------------------ ----------
/**
* Llamado por los usuarios de este Charset para obtener un codificador.
* crea una instancia de una clase privada (definida a continuación) y la pasa
* un codificador del Charset base.
*/
público CharsetEncoder nuevoEncoder() {
devolver nuevo Rot13Encoder (esto, baseCharset.newEncoder());
}
/**
* Llamado por los usuarios de este Charset para obtener un decodificador.
* crea una instancia de una clase privada (definida a continuación) y la pasa
* un decodificador del Charset base.
*/
público CharsetDecoder nuevoDecodificador() {
devolver nuevo Rot13Decoder (esto, baseCharset.newDecoder());
}
/**
* Este método debe implementarse mediante Charsets concretos. Siempre decimos que no.
* que es seguro.
*/
booleano público contiene (juego de caracteres cs) {
retorno (falso);
}
/**
* Rutina común para rotar todos los caracteres alfa ASCII en el dado
* CharBuffer por 13. Tenga en cuenta que este código compara explícitamente las partes superior y
* caracteres ASCII en minúscula en lugar de utilizar los métodos
* Character.isLowerCase y Character.isUpperCase Esto se debe a que.
* El esquema de rotación por 13 solo funciona correctamente para los caracteres alfabéticos de
* el juego de caracteres ASCII y esos métodos pueden devolver verdadero para Unicode no ASCII
* caracteres.
*/
rot13 vacío privado (CharBuffer cb) {
for (int pos = cb.posición(); pos < cb.limit(); pos++) {
char c = cb.get(pos);
char a = '/u0000';
// ¿Es alfa minúscula?
si ((c >= 'a') && (c <= 'z')) {
a = 'a';
}
// ¿Es alfa mayúscula?
si ((c >= 'A') && (c <= 'Z')) {
a = 'A';
}
// Si es así, tiralo por 13
si (a != '/u0000') {
c = (char) ((((c - a) + 13) % 26) + a);
cb.put(pos, c);
}
}
}
//------------------------------------------------ --------
/**
* La implementación del codificador para Rot13 Chars et.
* la clase de decodificador coincidente a continuación también debe anular los métodos "impl",
* como implOnMalformedInput() y realizar llamadas de paso al
* Objeto baseEncoder. Que se deja como ejercicio para el hacker.
*/
la clase privada Rot13Encoder extiende CharsetEncoder {
baseEncoder CharsetEncoder privado;
/**
* Constructor, llama al constructor de superclase con el objeto Charset
* y los tamaños de codificaciones del codificador delegado.
*/
Rot13Encoder(Charset cs, CharsetEncoder baseEncoder) {
super(cs, baseEncoder.averageBytesPerChar(), baseEncoder
.maxBytesPerChar());
this.baseEncoder = baseEncoder;
}
/**
* Implementación del bucle de codificación Primero, aplicamos el Rot13.
* algoritmo de codificación al CharBuffer, luego reinicie el codificador para
* el Charset base y llama a su método encode() para hacer lo real
* codificación. Es posible que esto no funcione correctamente con conjuntos de caracteres no latinos.
* El CharBuffer ingresado puede ser de solo lectura o reutilizado por la persona que llama para
* otros propósitos, por lo que lo duplicamos y aplicamos la codificación Rot13 al
* copiar. QUEREMOS avanzar la posición del búfer de entrada a.
* reflejan los caracteres consumidos.
*/
CoderResult protegido encodeLoop (CharBuffer cb, ByteBuffer bb) {
CharBuffer tmpcb = CharBuffer.allocate(cb.remaining());
mientras (cb.hasRemaining()) {
tmpcb.put(cb.get());
}
tmpcb.rebobinar();
rot13(tmpcb);
baseEncoder.reset();
CoderResult cr = baseEncoder.encode(tmpcb, bb, true);
// Si se produce un error o se desborda la salida, debemos ajustar
// la posición del buffer de entrada para que coincida con lo que
// realmente se consumió del búfer temporal.
// desbordamiento insuficiente (todas las entradas consumidas), esto no es operativo.
cb.posición(cb.posición() - tmpcb.restante());
retorno(cr);
}
}
//------------------------------------------------ --------
/**
* La implementación del decodificador para Rot13 Charset.
*/
la clase privada Rot13Decoder extiende CharsetDecoder {
baseDecoder CharsetDecoder privado;
/**
* Constructor, llama al constructor de superclase con el objeto Charset
* y pasar los valores de caracteres/bytes del decodificador delegado.
*/
Rot13Decoder(Charset cs, CharsetDecoder baseDecoder) {
super(cs, baseDecoder.averageCharsPerByte(), baseDecoder
.maxCharsPerByte());
this.baseDecoder = baseDecoder;
}
/**
* Implementación del bucle de decodificación Primero, reiniciamos el decodificador.
* el juego de caracteres base, luego llámelo para decodificar los bytes en caracteres,
* guardar el código de resultado. Luego, el CharBuffer se decodifica con el
* Se devuelve el algoritmo Rot13 y el código de resultado. Es posible que esto no funcione.
* correctamente para conjuntos de caracteres no latinos.
*/
CoderResult protegido decodeLoop (ByteBuffer bb, CharBuffer cb) {
baseDecoder.reset();
Resultado de CoderResult = baseDecoder.decode(bb, cb, true);
rot13(cb);
retorno (resultado);
}
}
//------------------------------------------------ --------
/**
* Prueba unitaria para el conjunto de caracteres Rot13. Este main( ) abrirá y leerá una entrada.
* Archivo si se nombra en la línea de comandos, o stdin si no se proporcionan args, y
* Escriba el contenido a STDOT a través de la codificación de charset x -ROT13.
* El "cifrado" implementado por el algoritmo ROT13 es simétrico.
* En un archivo de texto sencillo, como el código fuente de Java, por ejemplo, emitirá un
* Versión revuelta.
* Documento de texto simple original.
*/
public static void main (string [] argv) lanza la excepción {
BufferedReader en;
if (argv. longitud> 0) {
// Abra el archivo con nombre
in = new BufferedReader (nuevo FileReader (argv [0]));
} demás {
// envuelve un lector de topes alrededor de Stdin
in = new BufferedReader (new InputStreamReader (System.in));
}
// Crear un PintStream que use la codificación ROT13
PrintStream out = new PrintStream (System.out, False, "X -ROT13");
Cadena s = nula;
// Lea todas las entradas y escríbala en la salida.
// A medida que los datos pasan a través de PrintStream,
// estará codificado por ROT13.
while ((s = in.readline ())! = null) {
out.println (s);
}
salida.flush();
}
}
Ejemplo 6-4.
paquete com.ronsoft.books.nio.charset;
import java.nio.charset.charset;
import java.nio.charset.spi.charsetProvider;
importar java.util.HashSet;
import java.util.iterator;
/**
* Una clase CharsetProvider que pone a disposición los Charsets proporcionados por
* Ronsoft.
* No es un Charset IANA registrado, por lo que su nombre comienza con "X-" para evitar el nombre
* enfrentamientos con charsets oficiales.
*
* Para activar este CharsetProvider, es necesario agregar un archivo al
* classpath del tiempo de ejecución JVM en la siguiente ubicación:
* Meta-Inf/Services/java.nio.charsets.spi.charsetProvider
*
* Ese archivo debe contener una línea con el nombre totalmente calificado de esta clase en
* Una línea por sí misma: com.ronsoft.books.nio.charset.ronsoftcharsetprovider java
* NIO 216
*
* Consulte la página Javadoc para java.nio.charsets.spi.charsetProvider para completar
* detalles.
*
* @author Ron Hitchens ([email protected])
*/
clase pública RonsoftcharsetProvider extiende CharsetProvider {
// El nombre del charset que proporcionamos
String final estática privada Charset_name = "X-ROT13";
// un mango al objeto Charset
Charset privado ROT13 = nulo;
/**
* Constructor, instanciar un objeto Charset y guardar la referencia.
*/
public ronsoftcharsetProvider () {
this.rot13 = new Rot13CharSet (Charset_Name, nueva cadena [0]);
}
/**
* Llamado por métodos estáticos Charset para encontrar un charset en particular.
* Es el nombre de este charset (no tenemos ningún alias) y luego devuelve el
* ROT13 Charset, de lo contrario regresa nulo.
*/
public Charset CharsetForname (String CharSetName) {
if (charsetName.equalSignorEcase (charset_name)) {
return (rot13);
}
return (nulo);
}
/**
* Devuelve un iterador sobre el conjunto de objetos de charset que proporcionamos.
*
* @return Un objeto iterador que contiene referencias a todos los charset
* Objetos proporcionados por esta clase.
*/
Public Iterator <Harset> charsets () {
Hashset <Harset> set = new Hashset <Harset> (1);
set.add (rot13);
return (set.iterator ());
}
}
Agregar x -ROT13 a la lista de set de caracteres en el ejemplo 6-1 produce esta salida 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 (clase de conjunto de caracteres)
Un esquema de codificación del conjunto de caracteres que encapsula la codificación utilizada para representar secuencias de caracteres que son diferentes del conjunto de caracteres como una secuencia de bytes.
CharsetEncoder (clase de codificación del conjunto de caracteres)
La codificación del motor convierte secuencias de caracteres en secuencias de bytes. La secuencia de bytes se puede decodificar para reconstruir la secuencia de caracteres de origen.
CharsetDecoder (clase de decodificador de charset)
El motor de decodificación convierte la secuencia de byte codificada en una secuencia de caracteres.
CharsetProvider SPI (proveedor de charset SPI)
Localice y haga que la implementación de Charset esté disponible a través del mecanismo del proveedor del servidor para su uso en el entorno de tiempo de ejecución.