character encoding - tabla - ¿Cuál es la codificación binario a texto más eficiente?
tipos de codificaciones (8)
Actualmente, la base91 es la mejor codificación si no desea utilizar caracteres no imprimibles.
Ir por encima de esa base122 ayudará a aumentar la eficiencia un poco, pero no es una limpieza de 8 bits. Sin embargo, debido a que se basa en la codificación UTF-8, debería estar bien para su uso para muchos propósitos
Los contendientes más cercanos que pude encontrar hasta ahora son yEnc (2%) y ASCII85 (25% de gastos generales). Parece que hay algunos problemas en torno a yEnc, principalmente por el hecho de que utiliza un conjunto de caracteres de 8 bits. Lo que lleva a otro pensamiento: ¿existe un código binario para codificación de texto basado en el conjunto de caracteres UTF-8?
Esto realmente depende de la naturaleza de los datos binarios y de las restricciones que el "texto" coloca en su salida.
En primer lugar, si sus datos binarios no están comprimidos, intente comprimirlos antes de codificarlos. Entonces podemos asumir que la distribución de 1/0 o bytes individuales es más o menos aleatoria.
Ahora: ¿por qué necesitas texto? Normalmente, es porque el canal de comunicación no pasa a través de todos los caracteres por igual. por ejemplo, puede requerir texto ASCII puro, cuyos caracteres imprimibles van desde 0x20-0x7E. Tienes 95 caracteres para jugar. Cada carácter puede codificar teóricamente log2 (95) ~ = 6.57 bits por carácter. Es fácil definir una transformación que se acerca mucho.
Pero, ¿y si necesitas un personaje separador? Ahora solo tiene 94 caracteres, etc. Por lo tanto, la elección de una codificación realmente depende de sus requisitos.
Para tomar un ejemplo extremadamente estúpido: si su canal pasa los 256 caracteres sin problemas y no necesita separadores, puede escribir una transformada trivial que logre el 100% de eficiencia. :-) Como hacerlo queda como un ejercicio para el lector.
UTF-8 no es un buen transporte para datos binarios codificados arbitrariamente. Es capaz de transportar valores 0x01-0x7F con solo un 14% de sobrecarga. No estoy seguro de si 0x00 es legal; probablemente no Pero cualquier cosa por encima de 0x80 se expande a múltiples bytes en UTF-8. Yo trataría a UTF-8 como un canal restringido que pasa 0x01-0x7F, o 126 caracteres únicos. Si no necesita delimitadores, puede transmitir 6.98 bits por carácter.
Una solución general a este problema: asuma un alfabeto de N caracteres cuyas codificaciones binarias son 0 a N-1. (Si las codificaciones no son como se supone, entonces use una tabla de búsqueda para traducir entre nuestra representación intermedia 0..N-1 y lo que realmente envía y recibe).
Asume 95 caracteres en el alfabeto. Ahora: algunos de estos símbolos representarán 6 bits, y algunos representarán 7 bits. Si tenemos A símbolos de 6 bits y B símbolos de 7 bits, entonces:
A + B = 95 (número total de símbolos) 2A + B = 128 (número total de prefijos de 7 bits que se pueden hacer. Puede iniciar 2 prefijos con un símbolo de 6 bits, o uno con un símbolo de 7 bits. )
Resolviendo el sistema, obtienes: A = 33, B = 62. Ahora construyes una tabla de símbolos:
//buff is a unsigned character array containing the binary data
//N is the number of bytes to be encoded
string simple_encode(unsigned char *buff, int N)
{
string sEncode = "";
for(int i = 0; i<N; i++)
{
sEncode += (97 + (buff[i] >> 4));
sEncode += (97 + (buff[i] & 0x0F));
}
return sEncode;
}
//sbuff is a string containing the encoded ascii data
//szDecoded is an unsigned char array that has been allocated to 1/2
//the length of sbuff
//N is an integer pointer and returns the number of converted bytes
void simple_decode(string sbuff, unsigned char *szDecode, int *N)
{
*N = sbuff.length()/2;
for(int i=0; i < *N; i++)
{
szDecode[i] = ((sbuff.at(2*i)-97) << 4) + (sbuff.at(2*i+1)-97);
}
}
Para codificar, primero desplace 6 bits de entrada. Si esos seis bits son mayores o iguales a 100001, desplace otro bit. Luego busque el código de salida de 7 bits correspondiente, tradúzcalo para que quepa en el espacio de salida y envíe. Cambiará 6 o 7 bits de entrada en cada iteración.
Para decodificar, acepte un byte y conviértalo a código de salida en bruto. Si el código en bruto es menor que 0100001, desplace los 6 bits correspondientes a su salida. De lo contrario, cambie los 7 bits correspondientes a su salida. Estarás generando 6-7 bits de salida en cada iteración.
Para datos distribuidos uniformemente creo que esto es óptimo. Si sabe que tiene más ceros que unos en su fuente, puede asignar los códigos de 7 bits al inicio del espacio para que sea más probable que pueda usar un código de 7 bits.
Hace poco tuve la necesidad de codificar binario como ascii y esto es lo que se me ocurrió. No sé si este es el más eficiente (probablemente no) pero es simple y rápido. Básicamente, codifico un byte como hexadecimal pero en lugar de usar el conjunto básico (0-9, AF) que uso (ap). Debido a que el conjunto es continuo, no requiere ninguna búsqueda de tabla.
//buff is a unsigned character array containing the binary data //N is the number of bytes to be encoded string simple_encode(unsigned char *buff, int N) { string sEncode = ""; for(int i = 0; i<N; i++) { sEncode += (97 + (buff[i] >> 4)); sEncode += (97 + (buff[i] & 0x0F)); } return sEncode; } //sbuff is a string containing the encoded ascii data //szDecoded is an unsigned char array that has been allocated to 1/2 //the length of sbuff //N is an integer pointer and returns the number of converted bytes void simple_decode(string sbuff, unsigned char *szDecode, int *N) { *N = sbuff.length()/2; for(int i=0; i < *N; i++) { szDecode[i] = ((sbuff.at(2*i)-97) << 4) + (sbuff.at(2*i+1)-97); } }
Junto a los que figuran en Wikipedia , hay Bommanews:
B-News (o bommanews) fue desarrollado para elevar el peso de la sobrecarga inherente a la codificación UUEncode y Base64: utiliza un nuevo método de codificación para rellenar datos binarios en mensajes de texto. Este método consume más recursos de la CPU, pero logra reducir la pérdida de aproximadamente 40% para UUEncode a 3.5% (el punto decimal entre esos dígitos no es suciedad en su monitor), al tiempo que evita el uso de códigos de control ANSI en el mensaje. cuerpo.
Es comparable a yEnc: source
yEnc requiere menos uso de la CPU que B-News y alcanza aproximadamente el mismo bajo nivel de sobrecarga, pero no evita el uso de todos los códigos de control, solo deja de lado aquellos que se observaron (experimentalmente) que tienen efectos no deseados en algunos servidores, lo que significa que es algo menos compatible con RFC que B-News.
La respuesta corta sería: No, todavía no lo hay.
Me encontré con el problema con la codificación de tanta información en la cadena JSON, es decir, UTF-8 sin caracteres de control, barra invertida y comillas.
Salí e investigué cuántos bits puedes exprimir en bytes UTF-8 válidos. No estoy de acuerdo con las respuestas que indiquen que UTF-8 conlleva demasiados gastos generales. No es verdad.
Si tiene en cuenta solo las secuencias de un byte, es tan potente como el ASCII estándar. Significado de 7 bits por byte. Pero si recortas todos los caracteres especiales, te quedarás con algo como Ascii85.
Pero hay menos personajes de control en los planos superiores. Por lo tanto, si utiliza fragmentos de 6 bytes, podrá codificar 5 bytes por porción. En la salida, obtendrá cualquier combinación de caracteres UTF-8 de cualquier longitud (de 1 a 6 bytes).
Esto le dará un mejor resultado que Ascii85: 5/6 en lugar de 4/5, 83% de eficiencia en lugar de 80%. En teoría, será aún mejor con una mayor longitud de trozo: aproximadamente el 84% en trozos de 19 bytes.
En mi opinión, el proceso de codificación se vuelve demasiado complicado, mientras que proporciona muy poco beneficio. Así que Ascii85 o alguna versión modificada (ahora estoy viendo Z85 ) sería mejor.
Busqué la codificación binario a texto más eficiente el año pasado. Me di cuenta de que la compacidad no es el único criterio. Lo más importante es donde puedes usar cadenas codificadas. Por ejemplo, yEnc
tiene una sobrecarga del 2%, pero es una codificación de 8 bits, por lo que su uso es muy limitado.
Mi elección es Z85
. Tiene una sobrecarga aceptable del 25% y la cadena codificada se puede utilizar en casi todas partes: XML, JSON, código fuente, etc. Consulte la Z85 Z85 para obtener más detalles.
Finalmente, escribí la library Z85 en C / C ++ y la uso en producción.