Todo el mundo conoce la codificación UTF-8, que ha dominado durante mucho tiempo el espacio de Internet y se ha utilizado durante muchos años. Parece que todo se sabe sobre ella, y no hay nada interesante que contar sobre este tema. Si lee recursos populares como Wikipedia, entonces realmente no hay nada inusual allí, excepto que la versión en inglés menciona brevemente una historia extraña sobre cómo fue "esbozada en una servilleta en un restaurante".
De hecho, la invención de esta codificación no puede ser tan banal, aunque solo sea porque Ken Thompson, una persona legendaria, participó en su creación. Trabajó con Dennis Ritchie, fue uno de los creadores de UNIX, contribuyó al desarrollo de C (inventó su predecesor - B), y más tarde, mientras trabajaba en Google, participó en la creación del lenguaje Go.
Antes de usted: la traducción de varias letras en las que los desarrolladores recuerdan la historia de la creación de la codificación.
Caracteres:
ken (at) entrisphere.com - Ken Thompson
Ken Thompson (izquierda) con Dennis Ritchie
"Rob 'Commander' Pike" - Robert Pike , un programador canadiense que trabajó en UTF-8 con Ken Thompson
mkuhn (at) acm.org - Markus Kuhn , científico informático alemán
henry (arroba) spsystems.net - Henry Spurser , autor de una de las implementaciones de RegExp
Russ Cox < rsc@plan9.bell-labs.com > - Russ Cox , empleado de Bell Labs que trabajó en Plan 9
Greger sistema Leijonhufvud < greger@friherr.com> - Uno de los miembros del personal de X / Open
Plan 9 - El sistema operativo, que fue el primero en utilizar la codificación UTF-8 para proporcionar multilingüismo.
UTF-8: codificación de caracteres Unicode
Correspondencia 2003
A continuación se muestra la correspondencia entre los creadores de la codificación, Robert y Ken, que comenzó Robert Pike, quejándose de que su contribución a la creación de UTF-8 fue inmerecidamente olvidada. Robert le pide a uno de sus viejos conocidos que busque en los archivos del servidor de correo y encuentre pruebas de su participación. (aprox. por.)
Subject: UTF-8 history From: "Rob 'Commander' Pike" <r (at) google.com> Date: Wed, 30 Apr 2003 22:32:32 -0700 (Thu 06:32 BST) To: mkuhn (at) acm.org, henry (at) spsystems.net Cc: ken (at) entrisphere.com
Al mirar las conversaciones sobre los orígenes de UTF-8, veo que la misma historia se repite una y otra vez.
Versión equivocada:
- UTF-8 fue desarrollado por IBM.
- Se implementó en Plan 9 (un sistema operativo desarrollado por Bell Laboratories)
No es cierto. Vi de primera mano cómo se inventó UTF-8 en una servilleta una noche de septiembre de 1992 en un restaurante de Nueva Jersey.
Ocurrió de esta manera. Usamos el UTF ISO 10646 original para admitir caracteres de 16 bits en Plan 9, que odiamos, y estábamos listos para enviar Plan 9 cuando unos tipos me llamaron tarde una noche, creo que eran de IBM. Recuerdo haberlos conocido en la reunión del comité X / Open en Austin. Querían que Ken y yo viéramos su proyecto FSS / UTF.
(, ..) . Bell Labs , Plan 9 — , , , . , .Entendimos por qué querían cambiar el diseño y decidimos que esta es una buena oportunidad para usar nuestra experiencia para desarrollar un nuevo estándar y lograr que los chicos de X / Open lo promocionen. Tuvimos que contárselo, y estuvieron de acuerdo con la condición de que lo resolviéramos rápidamente.
Unicode , , , , , .
(. .)
Luego fuimos a comer algo, y durante la cena, Ken ordenó el paquete de ritmos, y cuando regresamos, llamaron a los chicos de X / Open y les explicaron nuestra idea. Enviamos nuestro boceto por correo, y ellos respondieron que era mejor que el de ellos (pero recuerdo exactamente que no nos mostraron su versión), y preguntaron cuándo podríamos implementarlo.
Una de las opciones para delimitar caracteres era una barra, pero esto podría confundir al sistema de archivos, podría interpretarlo como una secuencia de escape.Me parece que sucedió el miércoles por la noche. Prometimos que lanzaríamos el sistema el lunes, cuando creo que tienen programada una reunión importante. Esa noche, Ken escribió el código del codificador / decodificador y comencé a trabajar con C y las bibliotecas gráficas. Al día siguiente, el código estaba listo y comenzamos a convertir los archivos de texto del sistema. Para el viernes, Plan 9 ya estaba en funcionamiento en el llamado UTF-8.
(aprox. por.)
Y luego se reescribió un poco la historia.
¿Por qué no usamos su FSS / UTF?
Por lo que recuerdo, en esa primera llamada telefónica le canté a Desiderata mis requisitos de codificación, y FSS / UTF no tenía al menos una cosa: la capacidad de sincronizar un flujo de bytes tomados del medio del flujo usando tan pocos caracteres como sea posible para la sincronización (ver más arriba, sobre la definición de límites de caracteres.
les cantó Desiderat
.
, 1971 , : «Desiderata» , , : «». , « » « ». ( .)
, 1971 , : «Desiderata» , , : «». , « » « ». ( .)
Como no había solución en ninguna parte, éramos libres de hacerlo como quisiéramos.
Creo que "la historia fue inventada por IBM e implementada en Plan 9" tiene su origen en la documentación RFC 2279. Estábamos tan felices cuando UTF-8 echó raíces que no le contamos la historia a nadie.
Ninguno de nosotros trabaja más en Bell Labs, pero estoy seguro de que hay un archivo de correo electrónico que puede corroborar nuestra historia y puedo pedirle a alguien que investigue.
Así que todo el crédito es para los chicos de X / Open e IBM por hacerlo posible e impulsar la codificación, pero Ken lo desarrolló y yo lo ayudé con eso, sin importar lo que digan los libros de historia.
-Robar
Date: Sat, 07 Jun 2003 18:44:05 -0700 From: "Rob `Commander' Pike" <r@google.com> To: Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk> cc: henry@spsystems.net, ken@entrisphere.com, Greger Leijonhufvud <greger@friherr.com> Subject: Re: UTF-8 history
Le pedí a Russ Cox que investigara los archivos. Adjunto su mensaje. Creo que estará de acuerdo en que esto confirma la historia que publiqué anteriormente. El correo electrónico que enviamos a X / Open (creo que Ken editó y distribuyó este documento) incluye un nuevo "desiderátum número 6" sobre la detección de límites de caracteres.
Ya no sabremos qué impacto tuvo en nosotros la solución original de X / Open. Aunque son diferentes, tienen características comunes. No recuerdo haberlo visto en detalle, fue hace demasiado tiempo (en la última carta dice que X / Open no les mostró su implementación. Aprox. Lane) . Pero recuerdo muy bien cómo Ken escribió bocetos en una servilleta y luego deseó haberlo guardado.
-Robar
From: Russ Cox <rsc@plan9.bell-labs.com> To: r@google.com Subject: utf digging Date-Sent: Saturday, June 07, 2003 7:46 PM -0400
El archivo de arranque del usuario
/sys/src/libc/port/rune.c
fue modificado por division-heavy el 4 de septiembre de 1992. La versión en el volcado tiene un tiempo de 19:51:55. Al día siguiente se le agregó un comentario, pero por lo demás no cambió hasta el 14 de noviembre de 1996, cuando se
runelen
aceleró al verificar explícitamente el valor en
rune
lugar de usar el valor de retorno
runetochar
. El último cambio fue el 26 de mayo de 2001 cuando se agregó
runenlen
. (Rune es una estructura que contiene un valor Unicode. Runelen y runetochar son funciones que funcionan con este tipo de datos. Aprox. Trans.)
Hubo varias cartas de sus buzones de correo que se generaron mediante el trazado de líneas utf.
La primera es acerca de un archivo
utf.c
que es una copia
wctomb
y
mbtowc
(funciones de conversión de caracteres. Aprox. Per.) Que manejan la codificación UTF-8 completa de 6 bytes y 32 bits
runes.
Con la lógica de control de flujo se ve bastante feo. Supongo que este código vino del primer correo electrónico.
En
/usr/ken/utf/xutf
encontré una copia de lo que parece ser la fuente de ese método de codificación no auto-sincronizado, con el esquema UTF-8 adjunto al final del correo electrónico (comienza con "Definimos 7 tipos
byte
").
La versión de la carta a continuación, con fecha del 2 de septiembre a las 11:44:10 p.m., es la primera. Después de varias ediciones, en la mañana del 8 de septiembre salió la segunda versión. Los registros del servidor de correo muestran cómo se envía la segunda versión de la carta y, después de un tiempo, regresa a Ken:
helix: Sep 8 03:22:13: ken: upas/sendmail: remote inet!xopen.co.uk!xojig >From ken Tue Sep 8 03:22:07 EDT 1992 (xojig@xopen.co.uk) 6833 helix: Sep 8 03:22:13: ken: upas/sendmail: delivered rob From ken Tue Sep 8 03:22:07 EDT 1992 6833 helix: Sep 8 03:22:16: ken: upas/sendmail: remote pyxis!andrew From ken Tue Sep 8 03:22:07 EDT 1992 (andrew) 6833 helix: Sep 8 03:22:19: ken: upas/sendmail: remote coma!dmr From ken Tue Sep 8 03:22:07 EDT 1992 (dmr) 6833 helix: Sep 8 03:25:52: ken: upas/sendmail: delivered rob From ken Tue Sep 8 03:24:58 EDT 1992 141 helix: Sep 8 03:36:13: ken: upas/sendmail: delivered ken From ken Tue Sep 8 03:36:12 EDT 1992 6833
Buena suerte.
Archivos del archivo de correo
El siguiente es un archivo con correspondencia del volcado del servidor de correo, que Russ Cox adjuntó al suyo, en respuesta a la solicitud de Robert de profundizar en la historia. Esta es la primera versión". (aprox.)
>From ken Fri Sep 4 03:37:39 EDT 1992
Aquí está nuestra sugerencia para modificar FSS-UTF. Es casi lo mismo que en el anterior. Le pido disculpas al autor.
El código ha sido probado hasta cierto punto y debería estar en bastante buena forma. Rediseñamos el código del Plan 9 para usar esta codificación, y lanzaremos la distribución y seleccionaremos a los usuarios universitarios para las pruebas iniciales.
Formato de transformación de juego de caracteres universal seguro del sistema de archivos (FSS-UTF)
Con el establecimiento de ISO / IEC 10646 (Unicode) como estándar internacional y la expectativa de una adopción generalizada de este Conjunto de caracteres codificados universal (UCS), los sistemas operativos históricamente basados en ASCII necesitan desarrollar formas de representar y manejar una gran cantidad de caracteres que puede codificar con el nuevo estándar. UCS tiene varios problemas que deben resolverse en sistemas operativos históricamente establecidos y el entorno de programación en C.
(El texto a continuación menciona "sistemas operativos históricos" varias veces. Aparentemente en el contexto de "trabajar históricamente con codificación ASCII". omitió este epíteto, o lo reemplazó con "existente", etc. carril aprox.)
El mayor problema es el esquema de codificación utilizado en UCS. A saber, la integración del estándar UCS con lenguajes de programación, sistemas operativos y utilidades existentes. Los problemas en los lenguajes de programación y los sistemas operativos se están abordando en todas las industrias, sin embargo, todavía nos enfrentamos al manejo de UCS por parte de los sistemas operativos y las utilidades.
Entre los problemas asociados con el manejo de UCS en sistemas operativos, el principal es la presentación de datos dentro del sistema de archivos. El concepto subyacente es dar soporte a los sistemas operativos existentes en los que se ha realizado la inversión y al mismo tiempo aprovechar la gran cantidad de caracteres que proporciona UCS.
UCS permite codificar texto multilingüe utilizando un solo juego de caracteres. Pero UCS y UTF no protegen los bytes nulos (el final de las líneas en algunos lenguajes. Aprox. Per.) Y / o una barra en ASCII /, lo que hace que la codificación sea incompatible con Unix. La siguiente propuesta proporciona un formato de transformación UCS compatible con Unix, de modo que los sistemas Unix puedan admitir texto multilingüe dentro de una única codificación.
Este formato de conversión de codificación está diseñado para codificar archivos como un paso intermedio hacia la compatibilidad total con UCS. Sin embargo, dado que casi todas las implementaciones de Unis enfrentan los mismos problemas de soporte de UCS, esta propuesta tiene como objetivo proporcionar compatibilidad de codificación general en esta etapa.
Propósito / Objetivo
Basándonos en la suposición, obtenemos que si se conocen casi todos los problemas de procesamiento y almacenamiento de UCS en los sistemas de archivos del SO, entonces necesitamos usar un formato de conversión de UCS que funcione sin violar la estructura del sistema operativo. El objetivo es que el proceso de conversión de formato se pueda utilizar para codificar el archivo.
Criterios para el formato de conversión
Las siguientes son pautas que se deben seguir al definir el formato de conversión UCS:
- Compatibilidad con sistemas de archivos existentes.
Está prohibido utilizar un byte nulo y una barra inclinada como parte del nombre del archivo. - .
ASCII. UCS, ASCII, ASCII. - UCS .
- .
- , , .
- , (. ..).
FSS-UTF
El formato de transformación UCS propuesto codifica valores UCS en un rango que
[0,0x7fffffff]
utiliza varios bytes por carácter y longitudes de 1, 2, 3, 4, 5 y 6 bytes. En todos los casos de codificación con más de un byte, el byte inicial determina el número de bytes utilizados, con el bit más significativo establecido en cada byte. Cada byte que no comienza con 10XXXXXX es el comienzo de una secuencia de caracteres UCS.
Una manera fácil de recordar el formato: el número de altos en el primer byte significa el número de bytes en un carácter multibyte.
Bits Hex Min Hex Max Byte Sequence in Binary 1 7 00000000 0000007f 0vvvvvvv 2 11 00000080 000007FF 110vvvvv 10vvvvvv 3 16 00000800 0000FFFF 1110vvvv 10vvvvvv 10vvvvvv 4 21 00010000 001FFFFF 11110vvv 10vvvvvv 10vvvvvv 10vvvvvv 5 26 00200000 03FFFFFF 111110vv 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv 6 31 04000000 7FFFFFFF 1111110v 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv
El valor del carácter UCD codificado en varios bytes es una concatenación de v-bits. Si son posibles varios métodos de codificación, por ejemplo UCS 0, el más corto se considera aceptable.
A continuación se muestran ejemplos de implementaciones de funciones C estándar
wcstombs()
y
mbstowcs()
que demuestran algoritmos para convertir de UCS a formato de conversión y convertir de formato de conversión a UCS. Los ejemplos de implementaciones incluyen la verificación de errores, algunos de los cuales pueden no ser necesarios para mantener la coherencia:
typedef
struct
{
int cmask;
int cval;
int shift;
long lmask;
long lval;
} Tab;
static
Tab tab[] =
{
0x80, 0x00, 0*6, 0x7F, 0, /* 1 byte sequence */
0xE0, 0xC0, 1*6, 0x7FF, 0x80, /* 2 byte sequence */
0xF0, 0xE0, 2*6, 0xFFFF, 0x800, /* 3 byte sequence */
0xF8, 0xF0, 3*6, 0x1FFFFF, 0x10000, /* 4 byte sequence */
0xFC, 0xF8, 4*6, 0x3FFFFFF, 0x200000, /* 5 byte sequence */
0xFE, 0xFC, 5*6, 0x7FFFFFFF, 0x4000000, /* 6 byte sequence */
0, /* end of table */
};
int
mbtowc(wchar_t *p, char *s, size_t n)
{
long l;
int c0, c, nc;
Tab *t;
if(s == 0)
return 0;
nc = 0;
if(n <= nc)
return -1;
c0 = *s & 0xff;
l = c0;
for(t=tab; t->cmask; t++) {
nc++;
if((c0 & t->cmask) == t->cval) {
l &= t->lmask;
if(l < t->lval)
return -1;
*p = l;
return nc;
}
if(n <= nc)
return -1;
s++;
c = (*s ^ 0x80) & 0xFF;
if(c & 0xC0)
return -1;
l = (l<<6) | c;
}
return -1;
}
int
wctomb(char *s, wchar_t wc)
{
long l;
int c, nc;
Tab *t;
if(s == 0)
return 0;
l = wc;
nc = 0;
for(t=tab; t->cmask; t++) {
nc++;
if(l <= t->lmask) {
c = t->shift;
*s = t->cval | (l>>c);
while(c > 0) {
c -= 6;
s++;
*s = 0x80 | ((l>>c) & 0x3F);
}
return nc;
}
}
return -1;
}
>From ken Tue Sep 8 03:24:58 EDT 1992
La envié por correo, pero la carta se fue a un agujero negro, por lo que no recibí mi copia. Esta dirección de Internet debe haber estado en coma.
Segunda versión de la carta, con revisiones.
Luego se adjunta una copia de la carta, que se describe anteriormente como: "Después de varias correcciones, en la mañana del 8 de septiembre, salió la segunda versión". La parte que se repite está oculta debajo del spoiler. (aprox. traducción)
>From ken Tue Sep 8 03:42:43 EDT 1992
Finalmente obtuve mi copia.
--- /usr/ken/utf/xutf from dump of Sep 2 1992 ---
Texto oculto
ISO/IEC 10646 (Unicode) (UCS), , ASCII, , . UCS , C.
, UCS. UCS , . , UCS .
, UCS , . , , , , UCS.
UCS . UCS UTF ( . . .) / ASCII /, Unix. UCS, Unix, , , Unix- .
, UCS. , Unis UCS, .
, UCS , UCS, . , .
, , UCS:
UCS UCS
1, 2, 3, 4, 5, 6 . , . , 10XXXXXX, UCS.
: .
UCD — v-. , UCS 0, .
C
, UCS UCS. , :
File System Safe Universal Character Set Transformation Format (FSS-UTF)
ISO/IEC 10646 (Unicode) (UCS), , ASCII, , . UCS , C.
, UCS. UCS , . , UCS .
, UCS , . , , , , UCS.
UCS . UCS UTF ( . . .) / ASCII /, Unix. UCS, Unix, , , Unix- .
, UCS. , Unis UCS, .
/
, UCS , UCS, . , .
, , UCS:
- .
. - .
ASCII. UCS, ASCII, ASCII. - UCS .
- .
- , , .
- , (. ..).
FSS-UTF
UCS UCS
[0,0x7fffffff]
1, 2, 3, 4, 5, 6 . , . , 10XXXXXX, UCS.
: .
Bits Hex Min Hex Max Byte Sequence in Binary 1 7 00000000 0000007f 0vvvvvvv 2 11 00000080 000007FF 110vvvvv 10vvvvvv 3 16 00000800 0000FFFF 1110vvvv 10vvvvvv 10vvvvvv 4 21 00010000 001FFFFF 11110vvv 10vvvvvv 10vvvvvv 10vvvvvv 5 26 00200000 03FFFFFF 111110vv 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv 6 31 04000000 7FFFFFFF 1111110v 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv
UCD — v-. , UCS 0, .
C
wcstombs()
mbstowcs()
, UCS UCS. , :
typedef
struct
{
int cmask;
int cval;
int shift;
long lmask;
long lval;
} Tab;
static
Tab tab[] =
{
0x80, 0x00, 0*6, 0x7F, 0, /* 1 byte sequence */
0xE0, 0xC0, 1*6, 0x7FF, 0x80, /* 2 byte sequence */
0xF0, 0xE0, 2*6, 0xFFFF, 0x800, /* 3 byte sequence */
0xF8, 0xF0, 3*6, 0x1FFFFF, 0x10000, /* 4 byte sequence */
0xFC, 0xF8, 4*6, 0x3FFFFFF, 0x200000, /* 5 byte sequence */
0xFE, 0xFC, 5*6, 0x7FFFFFFF, 0x4000000, /* 6 byte sequence */
0, /* end of table */
};
int
mbtowc(wchar_t *p, char *s, size_t n)
{
long l;
int c0, c, nc;
Tab *t;
if(s == 0)
return 0;
nc = 0;
if(n <= nc)
return -1;
c0 = *s & 0xff;
l = c0;
for(t=tab; t->cmask; t++) {
nc++;
if((c0 & t->cmask) == t->cval) {
l &= t->lmask;
if(l < t->lval)
return -1;
*p = l;
return nc;
}
if(n <= nc)
return -1;
s++;
c = (*s ^ 0x80) & 0xFF;
if(c & 0xC0)
return -1;
l = (l<<6) | c;
}
return -1;
}
int
wctomb(char *s, wchar_t wc)
{
long l;
int c, nc;
Tab *t;
if(s == 0)
return 0;
l = wc;
nc = 0;
for(t=tab; t->cmask; t++) {
nc++;
if(l <= t->lmask) {
c = t->shift;
*s = t->cval | (l>>c);
while(c > 0) {
c -= 6;
s++;
*s = 0x80 | ((l>>c) & 0x3F);
}
return nc;
}
}
return -1;
}
int mbtowc(wchar_t *p, const char *s, size_t n) { unsigned char *uc; /* so that all bytes are nonnegative */ if ((uc = (unsigned char *)s) == 0) return 0; /* no shift states */ if (n == 0) return -1; if ((*p = uc[0]) < 0x80) return uc[0] != '\0'; /* return 0 for '\0', else 1 */ if (uc[0] < 0xc0) { if (n < 2) return -1; if (uc[1] < 0x80) goto bad; *p &= 0x3f; *p <<= 7; *p |= uc[1] & 0x7f; *p += OFF1; return 2; } if (uc[0] < 0xe0) { if (n < 3) return -1; if (uc[1] < 0x80 || uc[2] < 0x80) goto bad; *p &= 0x1f; *p <<= 14; *p |= (uc[1] & 0x7f) << 7; *p |= uc[2] & 0x7f; *p += OFF2; return 3; } if (uc[0] < 0xf0) { if (n < 4) return -1; if (uc[1] < 0x80 || uc[2] < 0x80 || uc[3] < 0x80) goto bad; *p &= 0x0f; *p <<= 21; *p |= (uc[1] & 0x7f) << 14; *p |= (uc[2] & 0x7f) << 7; *p |= uc[3] & 0x7f; *p += OFF3; return 4; } if (uc[0] < 0xf8) { if (n < 5) return -1; if (uc[1] < 0x80 || uc[2] < 0x80 || uc[3] < 0x80 || uc[4] < 0x80) goto bad; *p &= 0x07; *p <<= 28; *p |= (uc[1] & 0x7f) << 21; *p |= (uc[2] & 0x7f) << 14; *p |= (uc[3] & 0x7f) << 7; *p |= uc[4] & 0x7f; if (((*p += OFF4) & ~(wchar_t)0x7fffffff) == 0) return 5; } bad:; errno = EILSEQ; return -1; }
Definimos 7 tipos de bytes:
T0 0xxxxxxx 7 free bits Tx 10xxxxxx 6 free bits T1 110xxxxx 5 free bits T2 1110xxxx 4 free bits T3 11110xxx 3 free bits T4 111110xx 2 free bits T5 111111xx 2 free bits
La codificación se ve así:
>From hex Thru hex Sequence Bits 00000000 0000007f T0 7 00000080 000007FF T1 Tx 11 00000800 0000FFFF T2 Tx Tx 16 00010000 001FFFFF T3 Tx Tx Tx 21 00200000 03FFFFFF T4 Tx Tx Tx Tx 26 04000000 FFFFFFFF T5 Tx Tx Tx Tx Tx 32
Algunas notas:
- Dos bytes pueden codificar potencia de 2 ^ 11 caracteres, pero solo se utilizarán 2 ^ 11-2 ^ 7. Los códigos en el rango 0-7F se considerarán inválidos. Creo que esto es mejor que agregar un montón de constantes "mágicas" sin ningún beneficio real. Esta observación se aplica a todas las secuencias más largas.
- Las secuencias de 4, 5 y 6 bytes existen solo por razones políticas. Preferiría eliminarlos.
- La secuencia de 6 bytes abarca 32 bits, la propuesta FSS-UTF solo abarca 31.
- Todas las secuencias se sincronizan con cualquier byte que no sea
Tx.
***
Esta breve correspondencia puso todo en su lugar. Aunque esa "servilleta legendaria" no ha sobrevivido, hubo suficientes extractos del archivo del servidor de correo para que la comunidad reconociera sus méritos. Wikipedia agregó los nombres de Ken y Robert y un dato curioso sobre una servilleta en un restaurante, y en Internet esta historia circula y se comenta "tal cual", en forma de texto simple que contiene varias letras y parte de un volcado del servidor de correo.
El sistema operativo Plan 9 ha sido olvidado hace mucho tiempo, nadie recuerda para qué fue escrito y por qué fue el "número nueve", y UTF-8, casi treinta años después, sigue siendo relevante y no se va a retirar.
Parecería que esto es solo una codificación, pero incluso una historia tan simple puede ser entretenida si profundizas un poco en ella. En los albores del desarrollo tecnológico, era imposible predecir qué se dispararía y pasaría a la historia, y qué se olvidaría.
Fuente de archivos