web-dev-qa-db-fra.com

Compression de chaîne courte vraiment simple

Existe-t-il une technique de compression très simple pour les chaînes d'une longueur maximale de 255 caractères (oui, je compresse URL )?

Je ne suis pas préoccupé par la force de la compression - je recherche quelque chose qui fonctionne très bien et qui est rapide à mettre en œuvre. Je voudrais quelque chose de plus simple que SharpZipLib : quelque chose qui peut être implémenté avec quelques méthodes courtes.

22
cbp

Je pense que la question clé ici est " Pourquoi voulez-vous compresser les URL? "

Essayer de raccourcir les longues URL pour la barre d'adresse?

Vous feriez mieux de stocker l'URL d'origine quelque part (base de données, fichier texte ...) à côté d'un hashcode de la partie non-domaine (MD5, très bien). Vous pouvez alors avoir une simple page (ou un HTTPModule si vous vous sentez flashy) pour lire le MD5 et rechercher la vraie URL. C’est ainsi que TinyURL et d’autres travaillent.

Par exemple:

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

Peut être raccourci à:

http://mydomain.com/2d4f1c8a

L'utilisation d'une bibliothèque de compression pour cela ne fonctionnera pas . La chaîne sera compressée dans une représentation binaire plus courte, mais la conversion de cette chaîne en une chaîne qui doit être valide en tant que partie d'une URL (par exemple, Base64) annulera tout avantage que vous auriez tiré de la compression.

Stocker beaucoup d'URL en mémoire ou sur disque?

Utilisez la bibliothèque de compression intégrée dans System.IO.Compression ou la bibliothèque ZLib qui est simple et incroyablement bonne. Étant donné que vous allez stocker des données binaires, la sortie compressée sera correcte telle quelle. Vous devrez le décompresser pour l'utiliser en tant qu'URL.

20
badbod99

Comme suggéré dans la réponse acceptée , l'utilisation de la compression des données ne permet pas de raccourcir les chemins d'URL qui sont déjà assez courts.

DotNetZip a une classe DeflateStream qui expose une méthode statique (Partagé en VB) CompressString . C'est un moyen d'une ligne de compresser une chaîne en utilisant DEFLATE ( RFC 1951 ). L'implémentation DEFLATE est entièrement compatible avec System.IO.Compression.DeflateStream , mais DotNetZip se compresse mieux. Voici comment vous pourriez l'utiliser:

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);
    }
}

En utilisant ce code, voici mes résultats de test:

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

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

Ainsi, vous pouvez voir que le tableau d'octets "compressé", lorsqu'il est représenté en hexadécimal, est plus long que l'original, environ deux fois plus longtemps. La raison en est qu'un octet hexadécimal correspond en fait à 2 ASCII caractères.

Vous pouvez compenser quelque peu cela en utilisant une base 62, au lieu d'une base 16 (hex) pour représenter le nombre. Dans ce cas, a-z et A-Z sont également des chiffres, ce qui vous donne 0-9 (10) + a-z (+26) + A-Z (+26) = 62 chiffres au total. Cela réduirait considérablement la production. Je n'ai pas essayé ça. encore.


EDIT
Ok, j'ai testé le codeur Base-62. Cela raccourcit la chaîne hexagonale d'environ la moitié. Je pensais que cela réduirait à 25% (62/16 = ~ 4), mais je pense que je perds quelque chose avec la discrétisation. Dans mes tests, la chaîne résultante encodée en base 62 a à peu près la même longueur que l'URL d'origine. Donc, non, utiliser la compression puis l'encodage en base 62 n'est toujours pas une bonne approche. vous voulez vraiment une valeur de hachage.

12
Cheeso

Je suggère de regarder dans le System.IO.Compression Namespace Il y a un article sur CodeProject qui peut aider.

3
Dan Diplo

Quel est ton but?

1
peSHIr

Je commencerais par essayer l’une des bibliothèques Zip existantes (source libre ou open source), par exemple. http://www.icsharpcode.net/OpenSource/SharpZipLib/

Zip devrait bien fonctionner pour les chaînes de texte, et je ne suis pas sûr qu'il soit utile de mettre en œuvre un algorithme de compression, votre nom ....

0
Grzenio

Avez-vous essayé simplement d’utiliser gzip ?

Aucune idée si cela fonctionnerait efficacement avec de telles chaînes courtes, mais je dirais que c'est probablement votre meilleur pari.

0
Justin

La bibliothèque open source SharpZipLib est facile à utiliser et vous fournira des outils de compression.

0
Wolfwyrd

Je viens de créer un schéma de compression qui cible les URL et réalise environ 50% de compression (par rapport à la représentation en base64 du texte de l'URL d'origine).

voir http://blog.alivate.com.au/packed-url/

0
Todd

Vous pouvez utiliser directement l'algorithme deflate, sans en-têtes de contrôle ni somme de contrôle, comme décrit dans cette question: Python: implémentations Inflate et Deflate

Cela réduit, selon mon test, une URL de 4 100 caractères à 1 270 caractères base64, ce qui lui permet de s’inscrire dans la limite de 2 000 d’IE.

Et voici un exemple d'URL de 4000 caractères , qui ne peut pas être résolu avec une table de hachage car l'applet peut exister sur n'importe quel serveur.

0
endolith