2012-05-16 17 views
25

Estoy bastante confundido sobre el concepto de codificación de caracteres .¿Qué es la codificación de caracteres y por qué debería molestarme con ella?

¿Qué es Unicode, GBK, etc.? ¿Cómo los usa un lenguaje de programación?

¿Debo molestarme en conocerlos? ¿Hay una manera más simple o más rápida de programar sin tener que preocuparme por ellos?

+6

El recurso clásico fuera del sitio para esto es el ensayo de Joel Spolsky [_El mínimo absoluto de cada desarrollador de software Absolutamente, definitivamente debe saber sobre Unicode y juegos de caracteres (Sin excusas!) _] (Http://www.joelonsoftware.com/ artículos/Unicode.html). – Raedwald

+1

Es una respuesta tardía, pero publiqué algunas explicaciones sobre las codificaciones y conjuntos de caracteres mencionados + también algunos accesos directos (por ejemplo, para Java) – bvdb

Respuesta

27

(Tenga en cuenta que estoy usando algunos de estos términos vagamente/coloquialmente para una explicación más simple que todavía golpea los puntos clave.)

Un byte sólo puede tener 256 valores distintos, siendo 8 bits.

Dado que hay conjuntos de caracteres con más de 256 caracteres en el conjunto de caracteres, no se puede decir en general que cada carácter es un byte.

Por lo tanto, debe haber asignaciones que describan cómo convertir cada carácter de un conjunto de caracteres en una secuencia de bytes. Algunos caracteres pueden asignarse a un solo byte, pero otros deberán asignarse a varios bytes.

Esas asignaciones son codificaciones, porque le indican cómo codificar caracteres en secuencias de bytes.

En cuanto a Unicode, en un nivel muy alto, Unicode es un intento de asignar un número único y único a cada carácter. Obviamente ese número tiene que ser algo más ancho que un byte ya que hay más de 256 caracteres :) Java usa una versión de Unicode donde a cada personaje se le asigna un valor de 16 bits (y es por eso que los caracteres Java son de 16 bits de ancho y tienen un entero valores de 0 a 65535). Cuando obtiene la representación de bytes de un carácter Java, debe indicarle a la JVM la codificación que desea utilizar para que sepa cómo elegir la secuencia de bytes para el carácter.

2

La codificación de caracteres es lo que utiliza para resolver el problema de escribir software para alguien que usa un idioma diferente al suyo.

No sabe cómo son los personajes y cómo se ordenan. Por lo tanto, no sabes cómo se verán las cadenas en este nuevo idioma en binario y, francamente, no te importa.

Lo que tienes es una forma de traducir cadenas del idioma que hablas al idioma que hablan (por ejemplo, un traductor). Ahora necesita un sistema que sea capaz de representar ambos idiomas en binario sin conflictos. La codificación es ese sistema.

Es lo que le permite escribir software que funciona independientemente de la forma en que se representan los idiomas en binario.

22

ASCII es fundamental

Originalmente 1 personaje siempre se almacena como 1 byte. Un byte (8 bits) tiene el potencial de distinguir 256 valores posibles. Pero, de hecho, , solo se usaron los primeros 7 bits. Entonces solo se definieron 128 caracteres. Este conjunto se conoce como con el juego de caracteres ASCII.

  • 0x00 - 0x1F contienen códigos de dirección (por ejemplo CR, LF, STX, ETX, EOT, BEL, ...)
  • 0x20 - 0x40 contienen números y puntuacion
  • 0x41 - 0x7F contienen caracteres alfabéticos mayoría
  • 0x80 - 0xFF el octavo bit = indefinido.

Francés, alemán y muchos otros idiomas necesitan caracteres adicionales. (por ejemplo, à, é, ç, ô, ...) que no estaban disponibles en el juego de caracteres ASCII. Entonces usaron el 8vo bit para definir sus personajes. Esto es lo que se conoce como "extended ASCII".

El problema es que el 1 bit adicional no tiene capacidad suficiente para cubrir todos los idiomas del mundo. Entonces, cada región tiene su propia variante ASCII. Hay muchas codificaciones ASCII extendidas (latin-1 siendo una muy popular).

pregunta popular: "Es un personaje ASCII o se trata de una codificación"? ASCII es un conjunto de caracteres. Sin embargo, en la programación charset y encoding se usan ampliamente como sinónimos. Si quiero hacer referencia a una codificación que solo contiene los caracteres ASCII y nada más (el 8vo bit es siempre 0): eso es US-ASCII.

Unicode da un paso más

Unicode también es un conjunto de caracteres (no una codificación). Utiliza los mismos caracteres como el estándar ASCII, pero amplía la lista con caracteres adicionales, lo que le da a cada carácter un punto de código en el formato u+xxxx. Tiene la ambición de contener todos los personajes (e iconos populares) utilizados en todo el mundo.

UTF-8, UTF-16 y UTF-32 son codificaciones que aplican la tabla de caracteres Unicode. Pero cada uno de ellos tiene una forma ligeramente diferente de cómo codificarlos. UTF-8 solo usará 1 byte al codificar un carácter ASCII, dando el mismo resultado que cualquier otra codificación ASCII. Pero para otros personajes, usará el primer bit para indicar que seguirá un segundo byte.

GBK es una codificación, que al igual que UTF-8 usa múltiples bytes. El primer byte sigue el estándar ASCII, por lo que solo se utilizan 7 bits. El octavo bit se usa para indicar la presencia de un segundo byte, que se usa para representar aproximadamente 22,000 caracteres chinos. Pero una diferencia importante es que este no respeta el conjunto de caracteres Unicode.

tipos Mime

tipos MIME son también confunde a menudo con codificaciones.

No hay una forma sencilla de decodificar un archivo. Hubiera sido ideal si todos los archivos contuvieran un prefijo para indicar en qué codificación se almacenaban sus datos. Al final, corresponde a la aplicación (o su desarrollador) determinar una codificación (por ej. US-ASCII, UTF-8, algunos valores predeterminados del sistema). ..).

Al enviar datos a través de Internet, existe el mismo problema.Afortunadamente, algunos protocolos, como HTTP, usan declaraciones de tipo MIME para especificar qué tipo de datos y conjunto de caracteres utilizan los datos. Un encabezado HTTP típico contiene esto:

Content-Type: text/html; charset=utf-8 

Pero para text/xml que no tendría sentido (un parámetro charset incluso serán ignorados). Los analizadores XML en general leerán la primera línea del archivo, buscando la etiqueta <?xml encoding=.... Si está allí, entonces volverán a abrir el archivo usando esa codificación.

El mismo problema existe when sending e-mails. Un correo electrónico puede contener un mensaje html o simplemente texto sin formato.

accesos directos

En caso de Java (y muchos otros lenguajes de programación), además de los peligros de las codificaciones, hay también la complejidad de fundición bytes y enteros a personajes debido a que su contenido se almacena en diferentes rangos.

  • un byte se almacena como un byte con signo (rango: -128 a 127).
  • el tipo char en Java se almacena en 2 bytes sin signo (rango: 0 - 65535)
  • una corriente devuelve un entero en el rango -1 a 255.

Si sabe que sus datos solo contienen valores ASCII. Luego, con la habilidad adecuada, puede analizar sus datos de bytes a caracteres o envolverlos inmediatamente en Cadenas.

// the -1 indicates that there is no data 
int input = stream.read(); 
if (input == -1) throw new EOFException(); 

// bytes must be made positive first. 
byte myByte = (byte) input; 
int unsignedInteger = myByte & 0xFF; 
char ascii = (char)(unsignedInteger); 

El acceso directo en Java es el uso de lectores y escritores y para especificar la codificación cuando se crea una instancia.

// wrap your stream in a reader. 
// specify the encoding 
// The reader will decode the data for you 
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); 

Como se ha explicado anteriormente para los archivos XML que no importa mucho, porque cualquier DOM decente o marshaller JAXB comprobará si hay un atributo de codificación.

+1

Solo una pequeña nota: Dado que casi todas las codificaciones codifican los 128 caracteres ASCII básicos de la misma manera, siempre como todos los caracteres usados ​​están definidos en este conjunto básico, puede codificar/decodificar su mensaje usando prácticamente cualquier codificación aleatoria. (por ejemplo, UTF-8, US-ASCII, latin-1, GBK, ...). – bvdb

+1

También es interesante la BOM (byte-order-mark) que se utiliza para codificaciones que usan múltiples bytes (por ejemplo, UTF-16). Indica cuál de los bytes es el primero (el más significativo). Este marcador-byte se coloca delante del mensaje. Otra buena razón para usar 'Reader' decente. – bvdb

+0

La tabla de caracteres de Unicode * es * una codificación por definición, sin embargo, tiene una codificación doble en i. mi. UTF-8. Por lo tanto, simplemente está mal, que Unicode no tiene codificación. –

Cuestiones relacionadas