8
votes

Compressez efficacement les chaînes de 10-1000 caractères en Java?

Je dois compresser des chaînes (écrites dans une langue connue mais variable) de n'importe où de 10 à 1000 caractères dans des paquets UDP individuels.

Quels algorithmes de compression disponibles en Java sont bien adaptés à cette tâche?

Y a-t-il peut-être des bibliothèques Java open source disponibles pour faire cela?


1 commentaires

Vous n'indiquez pas quel type de "efficace" vous parlez. Compression rapide? Décompression rapide? La plus petite taille comprimée? Vous n'êtes pas non plus d'indiquer si le texte est alphabétique (pour certains alphabet), syllabique ou basé sur des personnages (comme chinois / japonais / coréen) ... ou tout ce qui précède.


4 Réponses :


10
votes

"Cela dépend".

Je commencerais avec seulement les principaux candidats: LZMA ( "7-zip"), deflate (direct, zlib: deflate + petit emballage, gzip: dégonfler + emballage légèrement plus grand, zip: dégonfler + même emballage plus), bzip2 (je doute que ce serait que bon ici, fonctionne mieux avec une grande fenêtre relative), peut-être même l'un des autres LZ * branches comme LZS qui a une RFC pour IP compression Payload mais ...

... exécuter une analyse sur la base des données réelles et de compression / débit en utilisant plusieurs approches différentes. Java a à la fois GZIPOutputStream ( » dégonfler en emballage gzip ") et DeflaterOutputStream standard et là ( "dégonfler plaine", recommander sur gzip ou zip "emballages") sont LZMA implémentations Java (compresseur juste besoin, pas le contenant) si ceux-ci devraient tous être trivial à la maquette.

En cas de régularité entre les paquets alors il est possible ce qui pourrait être utilisé - par exemple construire les correspondances de cache, des tables de Huffman, ou simplement modifier les « fenêtres » de l'un des autres algorithmes - mais perte de paquets et « de compressibilité » besoins susceptibles d'être pris en compte. En descendant cette route si ajoute beaucoup plus de complexité . Plus d'idées pour aider le compresseur se trouvent à SO: Comment trouver un bon / optimal pour le dictionnaire zlib « setDictionary » lors du traitement d'un ensemble de données ?.

De plus, le protocole devrait probablement un simple « repli » de zéro compression parce que certains [en particulier les petites aléatoires] données pourraient ne pas être pratiquement compressible ou pourrait SO: meilleur algorithme de compression pour les chaînes court texte qui suggère Smaz , mais je ne sais pas comment cet algorithme transfert à unicode / binaire.

Voir également que tous les dégonfler (ou un autre format) mises en œuvre sont créés égaux. Je ne suis pas au courant de dégonflement standard de Java par rapport à une 3ème partie (disons JZlib ) en termes d'efficacité pour les petites données, mais considérez [Compresser petites charges utiles .NET] qui montre des nombres négatifs plutôt pour le format « la même compression ». L'article se termine aussi bien:

... il est généralement plus avantageux pour compresser de toute façon, et déterminer quelle charge utile (le comprimé ou un non compressé) a la plus petite taille et comprennent un petit jeton pour indiquer si la décompression est nécessaire.

Ma conclusion finale: toujours tester à l'aide des données du monde réel et de mesurer les avantages, ou vous pourriez être dans une petite surprise à la fin

codage heureux. Pour ce temps réel.


1 commentaires

"Compression de petites charges utiles [.NET]" Le lien est mort



5
votes

La chose la plus simple à faire serait de calmer une gzipOutputtream au-dessus d'une byearrayOutputStream, car elle est intégrée à la JDK, en utilisant

ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream zos = new GZIPOutputStream(baos);

zos.write(someText.getBytes());
zos.finish();
zos.flush();


byte[] udpBuffer = baos.toByteArray();


4 commentaires

+1 si vous utilisez le DEFLaterOutPutStream. ZIP ajoute simplement sur le protocole de déflèvement qui pourrait être significatif avec de telles petites données.


+1 pour l'exemple de code essentiel. Mais il faut utiliser DEFLATEROutPutStream ou GzipOutPutStream .


changé en gzipoutputtream comme suggéré


+1 :-) Le DeflaterOutPutStream doit toujours avoir un peu moins de frais généraux.



5
votes

La plupart des algorithithologiques de compression standard ne fonctionnent pas si bien avec de petites quantités de données. Souvent, il y a une en-tête et une somme de contrôle et il faut du temps pour que la compression soit réchauffeuse. C'est à dire. Il construit un dictionnaire de données basé sur les données qu'il a vues.

Pour cette raison, vous pouvez trouver que

  • Les petits paquets peuvent être plus petits ou de la même taille sans compression.
  • Une simple compression spécifique à l'application / protocole est meilleure
  • Vous devez fournir un dictionnaire de données précuitout à l'algorithme de compression et éliminer les en-têtes autant que possible.

    Je vais habituellement avec une deuxième option pour les petits paquets de données.


0 commentaires

1
votes

Un bon algorithme de compression pour les chaînes courtes / URL est la mise en œuvre de LZW, il est en Java et peut être facilement porté pour le GWT du client: https : //code.google.com/p/lzwj/source/browse/src/main/java/by/dev/madhead/lzwj/compress/lzw.java

Certaines remarques

  • Utilisez une longueur de mot de code de 9 bits pour les petites chaînes (bien que vous puissiez essayer ce qui est meilleur). Le rapport d'origine est de 1 (très petites chaînes, comprimées n'est pas plus grande que la chaîne d'origine) à 0,5 (cordes plus grandes)
  • En cas de client GWT pour les autres longueurs de mots de code, il était nécessaire d'ajuster le traitement de l'entrée / de la sortie au travail à l'autre, pour éviter les bogues lors de la soumission de la séquence de bits en long, qui est imitée pour JS.

    Je l'utilise pour les paramètres d'URL complexes codant dans le GWT client, ainsi que la série de codages de base64 et de la sérialisation autobeenne vers JSON.

    UPD: la mise en œuvre de base64 est ici: http://www.source-code.biz/base64Coder / Java Vous devez le changer pour faire de l'URL-Safe, c'est-à-dire de changer les caractères suivants:

  • '+' -> '-'
  • '/' -> '~'
  • '=' -> '_'