2009-07-28 9 views
22

¿Existe una técnica de compresión realmente simple para cadenas de hasta 255 caracteres de longitud (sí, estoy comprimiendo URLs)?Compresión de cadena corta realmente simple

No me preocupa la fuerza de la compresión: estoy buscando algo que funcione muy bien y sea rápido de implementar. Me gustaría algo más simple que SharpZipLib: algo que se puede implementar con un par de métodos cortos.

+0

¿Por qué? Probablemente haya una mejor manera de hacer lo que estás preguntando. –

+2

"Por qué" es ciertamente una buena respuesta. Sin embargo, como nota al margen, la codificación Huffman funciona muy bien para la compresión de texto simple sin tener que recurrir a bibliotecas externas y la compresión LZW. –

+2

posible duplicado de [Mejor algoritmo de compresión para cadenas de texto cortas] (http://stackoverflow.com/questions/1138345/best-compression-algorithm-for-short-text-strings) –

Respuesta

20

Creo que la pregunta clave aquí es "¿Por qué quiere comprimir URL?"

Intentando acortar las URL largas para la barra de direcciones?

Será mejor que almacene la URL original en alguna parte (base de datos, archivo de texto ...) junto con un código hash de la parte que no pertenece al dominio (MD5 está bien). A continuación, puede tener una página simple (o un HTTPModule si se siente llamativo) para leer el MD5 y buscar la URL real. Así es como TinyURL y otros trabajan.

Por ejemplo:

http://mydomain.com/folder1/folder2/page1.aspx 

Podría haber un cortocircuito a:

http://mydomain.com/2d4f1c8a 

Usando una biblioteca de compresión para que esto no va a funcionar. La cadena se comprimirá en una representación binaria más corta, pero convertirla de nuevo en una cadena que debe ser válida como parte de una URL (por ejemplo, Base64) anulará cualquier beneficio que haya obtenido de la compresión.

¿Almacena muchas URL en la memoria o en el disco?

Utilice la biblioteca integrada de compresión dentro de System.IO.Compression o la biblioteca ZLib que es simple e increíblemente buena. Como almacenará datos binarios, la salida comprimida estará bien tal como está.Deberá descomprimirlo para usarlo como una URL.

+7

Esa no es una respuesta a la pregunta. ¿Qué pasa si no tienes dónde almacenar la tabla hash? – endolith

+0

@endolith - El punto es que la compresión de cadenas no te ayudará aquí, solo lo relacionas con un hash o similar. Vea la respuesta de Cheeso para las compresiones de ejemplo del mundo real más largas y tan largas en el original cuando se vuelvan a convertir en URL válidas. Siempre tienes "en algún lugar" para almacenar un hash. ¡Codifíquelo en su código de redireccionamiento de URL si realmente tiene "ninguna parte" para almacenarlo! – badbod99

+1

No siempre tiene un lugar para almacenar una tabla hash, y no siempre hace que la URL sea más larga. http://en.wikipedia.org/wiki/Data_URI_scheme, por ejemplo – endolith

1

¿Cuál es tu objetivo?

+0

No me preocupa la fuerza de la compresión - Soy buscando algo que funcione muy bien y sea rápido de implementar. ¿Me puedes apuntar a base64? – cbp

+6

Base64 no va a comprimir nada :) –

+0

@Jon Grant: Correcto. Base64 fue una sugerencia estúpida. Solo funcionaría después de comprimir realmente para obtener algo que (tal vez) es más pequeño, pero todavía ascii. Han eliminado todo rastro de la sugerencia. – peSHIr

0

Comenzaría probando una de las bibliotecas zip existentes (de código abierto o libre), p. http://www.icsharpcode.net/OpenSource/SharpZipLib/

postal debería funcionar bien para cadenas de texto, y no estoy seguro de si vale la pena implementar un algoritmo de compresión yourserlf ....

0

¿Has probado usar gzip?

No tengo idea de si funcionaría eficazmente con tan pocas cadenas, pero diría que es probablemente la mejor opción. biblioteca

0

El código abierto SharpZipLib es fácil de usar y le proporcionará herramientas de compresión

12

Como se sugiere en the accepted answer, la compresión de datos no funciona para acortar las rutas de URL que ya son bastante cortas.

DotNetZip tiene una clase DeflateStream que expone un método estático (compartido en VB) CompressString. Es una forma de una línea para comprimir una cadena usando DEFLATE (RFC 1951). La implementación DEFLATE es totalmente compatible con System.IO.Compression.DeflateStream, pero DotNetZip se comprime mejor. He aquí cómo usted puede ser que lo utiliza:

string[] orig = { 
    "folder1/folder2/page1.aspx", 
    "folderBB/folderAA/page2.aspx", 
}; 
public void Run() 
{ 
    foreach (string s in orig) 
    { 
     System.Console.WriteLine("original : {0}", s); 
     byte[] compressed = DeflateStream.CompressString(s); 
     System.Console.WriteLine("compressed : {0}", ByteArrayToHexString(compressed)); 
     string uncompressed = DeflateStream.UncompressString(compressed); 
     System.Console.WriteLine("uncompressed: {0}\n", uncompressed); 
    } 
} 

El uso de ese código, aquí están mis resultados:

original : folder1/folder2/page1.aspx 
compressed : 4bcbcf49492d32d44f03d346fa0589e9a9867a89c5051500 
uncompressed: folder1/folder2/page1.aspx 

original : folderBB/folderAA/page2.aspx 
compressed : 4bcbcf49492d7272d24f03331c1df50b12d3538df4128b0b2a00 
uncompressed: folderBB/folderAA/page2.aspx 

Así se puede ver el conjunto de bytes "comprimido", cuando se representa en hexadecimal, es más largo que el original, aproximadamente 2 veces más largo. La razón es que un byte hexadecimal es realmente 2 caracteres ASCII.

Puede compensar un poco por eso utilizando base-62, en lugar de base-16 (hex) para representar el número. En ese caso, a-z y A-Z también son dígitos, que le dan 0-9 (10) + a-z (+26) + A-Z (+26) = 62 dígitos en total. Eso acortaría la producción significativamente. No he intentado eso. todavía.


EDITAR
Ok Probé el codificador Base-62. Acorta la cuerda hexagonal a la mitad. Pensé que lo reduciría al 25% (62/16 = ~ 4) Pero creo que estoy perdiendo algo con la discretización. En mis pruebas, la cadena codificada en base 62 resultante tiene aproximadamente la misma longitud que la URL original. Entonces, no, usar la compresión y luego la codificación de la base-62 todavía no es un buen enfoque. realmente quieres un valor hash

+0

Usar hexadecimal es bastante estúpido, no es un formato denso en absoluto. Usar base64 o incluso base85 y reemplazar los caracteres no válidos por los correctos (escapando de nuevo toma espacio) sin duda reducirá la salida. Aunque no tanto como usted dice, su matemática está apagada. Por supuesto, cuanto más cortos sean los URI, menor será la compresión que puede esperar, y también importa cuál sea el contexto. –

0

Puede utilizar desinflar algoritmo de forma directa, sin ningún tipo de comprobación encabezados o pies de página, como se describe en esta pregunta: Python: Inflate and Deflate implementations

Esto reduce una URL 4100 caracteres a 1270 caracteres base64, en mi prueba, que le permite encajar en el interior Límite 2000 de IE.

Y aquí hay un ejemplo de 4000-character URL, que no se puede resolver con una tabla hash, ya que la aplicación puede existir en cualquier servidor.

Cuestiones relacionadas