web-dev-qa-db-fra.com

Comment compresser une chaîne en Java?

J'utilise GZIPOutputStream ou ZIPOutputStream pour compresser une chaîne (ma string.length() est inférieure à 20), mais le résultat compressé est plus long que la chaîne d'origine.

Sur certains sites, des amis m'ont dit que c'était parce que ma chaîne d'origine était trop courte, GZIPOutputStream peut être utilisé pour compresser des chaînes plus longues.

alors, quelqu'un peut-il m'aider à compresser une chaîne?

Ma fonction est comme:

String compress(String original) throws Exception {

}

Mettre à jour:

import Java.io.ByteArrayOutputStream;
import Java.io.IOException;
import Java.util.Zip.GZIPOutputStream;
import Java.util.Zip.*;


//ZipUtil 
public class ZipUtil {
    public static String compress(String str) {
        if (str == null || str.length() == 0) {
            return str;
        }

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzip = new GZIPOutputStream(out);
        gzip.write(str.getBytes());
        gzip.close();
        return out.toString("ISO-8859-1");
    }

    public static void main(String[] args) throws IOException {
        String string = "admin";
        System.out.println("after compress:");
        System.out.println(ZipUtil.compress(string));
    }
}

Le résultat est :

alt text

48
user421851

Les algorithmes de compression ont presque toujours une certaine forme d'espace disque, ce qui signifie qu'ils ne sont efficaces que pour la compression de données suffisamment volumineuses pour que le temps système soit inférieur à la quantité d'espace économisé.

Compresser une chaîne de 20 caractères seulement n’est pas facile et n’est pas toujours possible. Si vous avez de la répétition, le codage de Huffman ou un codage simple en longueur peut être compressé, mais probablement pas beaucoup.

36
JesperE

Lorsque vous créez une chaîne, vous pouvez la considérer comme une liste de caractères, ce qui signifie que pour chaque caractère de votre chaîne, vous devez prendre en charge toutes les valeurs possibles de caractère. Du soleil docs

char: le type de données char est un seul caractère Unicode 16 bits. Il a une valeur minimale de '\ u0000' (ou 0) et une valeur maximale de '\ uffff' (ou 65 535 inclus). 

Si vous souhaitez prendre en charge un jeu de caractères réduit, vous pouvez écrire un algorithme de compression simple, analogue à une conversation binaire-> décimale-> hexadécimale radix. Vous passez de 65 536 (ou le nombre de caractères pris en charge par votre système cible) à 26 (alphabétique)/36 (alphanumérique), etc.

J'ai utilisé cette astuce plusieurs fois, par exemple en encodant des horodatages sous forme de texte (cible 36 +, source 10) - assurez-vous simplement que vous avez suffisamment de tests unitaires!

9
Jon Freedman

Si les mots de passe sont plus ou moins "aléatoires", vous n'avez pas de chance, vous ne pourrez pas obtenir une réduction significative de la taille.

Mais: Pourquoi avez-vous besoin de compresser les mots de passe? Peut-être que ce dont vous avez besoin n’est pas une compression, mais une sorte de valeur de hachage? Si vous devez simplement vérifier si un nom correspond à un mot de passe donné, vous n'avez pas besoin de sauvegarder le mot de passe, mais vous pouvez enregistrer le hachage d'un mot de passe. Pour vérifier si un mot de passe saisi correspond à un prénom, vous pouvez construire la valeur de hachage de la même manière et la comparer à la valeur de hachage enregistrée. Comme un hachage (Object.hashCode ()) est un entier, vous pourrez stocker les 20 hachages de mots de passe dans 80 octets).

7
Arne Deutsch

Votre ami est correct Gzip et Zip sont tous deux basés sur DEFLATE . Cet algorithme est destiné à un usage général et n'est pas destiné à l'encodage de petites chaînes.

Si vous en avez besoin, une solution possible est un codage et un décodage personnalisés HashMap<String, String>. Cela peut vous permettre de faire un simple mappage un à un:

HashMap<String, String> toCompressed, toUncompressed;

String compressed = toCompressed.get(uncompressed);
// ...
String uncompressed = toUncompressed.get(compressed);

Clairement, cela nécessite une configuration et n’est pratique que pour un petit nombre de chaînes.

6
Matthew Flaschen

L'algorithme Zip est une combinaison de LZW et Arbres de Huffman . Vous pouvez utiliser l'un de ces algorithmes séparément.

La compression est basée sur 2 facteurs:

  • la répétition de sous-chaînes dans votre chaîne d'origine (LZW): s'il y a beaucoup de répétitions, la compression sera efficace. Cet algorithme offre de bonnes performances pour la compression d'un texte long et simple, car les mots sont souvent répétés
  • le nombre de chaque caractère dans la chaîne comprimée (Huffman): plus la répartition entre les caractères est déséquilibrée, plus la compression sera efficace

Dans votre cas, vous devriez essayer l’algorithme LZW uniquement. Utilisée à la base, la chaîne peut être compressée sans ajouter de méta-informations: c'est probablement mieux pour la compression de chaînes courtes.

Pour l'algorithme de Huffman, l'arbre de codage doit être envoyé avec le texte compressé. Ainsi, pour un petit texte, le résultat peut être plus volumineux que le texte d'origine, à cause de l'arbre.

4
Benoit Courtine

Le codage de Huffman est une option judicieuse ici. Gzip et ses amis le font, mais leur travail consiste à créer un arbre de Huffman pour l’entrée, à l’envoyer, puis à envoyer les données encodées avec l’arbre. Si l'arborescence est grande par rapport aux données, il est possible que la taille ne soit pas sauvegardée.

Cependant, il est possible d'éviter d'envoyer une arborescence: à la place, vous faites en sorte que l'expéditeur et le destinataire en aient déjà une. Il ne peut pas être construit spécifiquement pour chaque chaîne, mais vous pouvez utiliser un seul arbre global pour coder toutes les chaînes. Si vous le construisez à partir de la même langue que les chaînes d'entrée (anglais ou autre), vous devriez tout de même obtenir une bonne compression, bien qu'elle ne soit pas aussi efficace qu'avec un arbre personnalisé pour chaque entrée.

4
Tom Anderson

Huffman Coding pourrait vous aider, mais seulement si votre petite chaîne contient beaucoup de caractères

4
Noel M

Si vous savez que vos chaînes sont principalement ASCII, vous pouvez les convertir en UTF-8.

byte[] bytes = string.getBytes("UTF-8");

Cela peut réduire la taille de la mémoire d'environ 50%. Cependant, vous obtiendrez un tableau d'octets et non une chaîne. Si vous l'écrivez dans un fichier, cela ne devrait pas poser de problème.

Pour reconvertir en chaîne:

private final Charset UTF8_CHARSET = Charset.forName("UTF-8");
...
String s = new String(bytes, UTF8_CHARSET);
2
rghome

Jetez un coup d'œil à l'algorithme de Huffman.

https://codereview.stackexchange.com/questions/44473/huffman-code-implementation

L'idée est que chaque caractère est remplacé par une séquence de bits, en fonction de leur fréquence dans le texte (plus la séquence est fréquente). 

Vous pouvez lire l'intégralité de votre texte et créer un tableau de codes, par exemple:

Code de symbole

un 0

s 10

e 110

m 111

L'algorithme construit une arborescence de symboles basée sur la saisie de texte. Plus vous avez de caractères, plus la compression sera mauvaise.

Mais selon votre texte, cela pourrait être efficace. 

0
live-love

L’amélioration de la chaîne compacte est disponible dans Java 9 https://openjdk.Java.net/jeps/254

Java.lang.String a maintenant:

valeur de l'octet final privé [];

0
Anurag Sharma

Vous ne voyez aucune compression se produire pour votre chaîne, car il vous faut au moins quelques centaines d'octets pour obtenir une compression réelle utilisant GZIPOutputStream ou ZIPOutputStream. Votre chaîne est trop petite (je ne comprends pas pourquoi vous avez besoin de compression pour la même chose).

Vérifiez la conclusion de cet article article

L'article montre également comment compresser et décompresser les données à la volée afin de réduire le trafic sur le réseau et améliorer les performances de votre applications client/serveur . Compression des données à la volée, cependant.. améliore les performances de applications client/serveur uniquement lorsque les objets en cours de compression sont plus que quelques centaines d'octets. Vous ne serait pas capable d'observer amélioration de la performance si le les objets étant compressés et transférés sont de simples objets String, par exemple.

0
YoK