it-swarm.com.de

Wie komprimiere ich einen String in Java?

Ich verwende GZIPOutputStream oder ZIPOutputStream, um einen String zu komprimieren (mein string.length() ist weniger als 20), aber das komprimierte Ergebnis ist länger als der ursprüngliche String.

Auf einer Website habe ich einige Freunde gefunden, die sagten, dass meine ursprüngliche Zeichenfolge zu kurz ist. GZIPOutputStream kann verwendet werden, um längere Zeichenfolgen zu komprimieren.

kann mir jemand helfen, einen String zu komprimieren?

Meine Funktion ist wie:

String compress(String original) throws Exception {

}

Aktualisieren:

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

Das Ergebnis ist :

alt text

48
user421851

Komprimierungsalgorithmen haben fast immer eine Form von Platzbedarf, was bedeutet, dass sie nur dann wirksam sind, wenn Daten komprimiert werden, die so groß sind, dass der Aufwand geringer ist als die Menge an eingespartem Speicherplatz.

Das Komprimieren eines nur 20 Zeichen langen Strings ist nicht zu einfach und nicht immer möglich. Bei Wiederholungen können Huffman-Codierung oder einfache Lauflängencodierung möglicherweise komprimiert werden, aber wahrscheinlich nicht sehr viel.

36
JesperE

Wenn Sie einen String erstellen, können Sie ihn als eine Liste von Zeichen ansehen. Dies bedeutet, dass Sie für jedes Zeichen in Ihrem String alle möglichen Werte von char unterstützen müssen. Aus der Sonne docs

char: Der char-Datentyp ist ein einzelnes 16-Bit-Unicode-Zeichen. Es hat einen Mindestwert von "\ u0000" (oder 0) und einen Höchstwert von "\ uffff" (oder einschließlich 65.535). 

Wenn Sie eine reduzierte Anzahl von Zeichen haben, die Sie unterstützen möchten, können Sie einen einfachen Kompressionsalgorithmus schreiben, der der Binär-> Dezimal-> Hex-Radix-Konvertierung entspricht. Sie gehen von 65.536 (oder wie viele Zeichen Ihr Zielsystem unterstützt) bis 26 (alphabetisch)/36 (alphanumerisch) usw.

Ich habe diesen Trick ein paar Mal verwendet, zum Beispiel das Kodieren von Zeitstempeln als Text (Ziel 36 +, Quelle 10). Stellen Sie nur sicher, dass Sie genügend Komponententests haben!

9
Jon Freedman

Wenn die Passwörter mehr oder weniger "zufällig" sind, haben Sie kein Glück, und Sie werden keine signifikante Verkleinerung erhalten.

Aber: Warum müssen Sie die Passwörter komprimieren? Vielleicht benötigen Sie keine Komprimierung, sondern eine Art Hashwert? Wenn Sie lediglich prüfen müssen, ob ein Name mit einem bestimmten Kennwort übereinstimmt, müssen Sie das Kennwort nicht speichern, sondern können den Hash eines Kennworts speichern. Um zu überprüfen, ob ein eingegebenes Kennwort mit einem bestimmten Namen übereinstimmt, können Sie den Hashwert auf dieselbe Weise erstellen und mit dem gespeicherten Hash vergleichen. Da ein Hash (Object.hashCode ()) ein Int ist, können Sie alle 20 Passwort-Hashes in 80 Byte speichern.

7
Arne Deutsch

Dein Freund hat recht. Sowohl gzip als auch zip basieren auf DEFLATE . Dies ist ein allgemeiner Algorithmus und ist nicht für die Codierung kleiner Strings vorgesehen.

Wenn Sie dies benötigen, ist eine mögliche Lösung eine benutzerdefinierte Kodierung und Dekodierung HashMap<String, String>. Auf diese Weise können Sie eine einfache Eins-zu-Eins-Zuordnung durchführen:

HashMap<String, String> toCompressed, toUncompressed;

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

Dies erfordert eindeutig ein Setup und ist nur für eine kleine Anzahl von Strings praktisch.

6

Der Zip-Algorithmus ist eine Kombination aus LZW und Huffman Trees . Sie können einen dieser Algorithmen separat verwenden.

Die Komprimierung basiert auf zwei Faktoren:

  • wiederholung von Teilzeichenketten in Ihrer ursprünglichen Kette (LZW): Wenn es viele Wiederholungen gibt, ist die Komprimierung effizient. Dieser Algorithmus hat gute Eigenschaften zum Komprimieren eines langen Klartextes, da Wörter häufig wiederholt werden
  • die Anzahl jedes Zeichens in der komprimierten Kette (Huffman): Je mehr die Aufteilung zwischen den Zeichen unsymmetrisch ist, desto effizienter ist die Komprimierung

In Ihrem Fall sollten Sie nur den LZW-Algorithmus ausprobieren. Grundsätzlich kann die Kette komprimiert werden, ohne dass Meta-Informationen hinzugefügt werden müssen. Dies ist wahrscheinlich besser für die Komprimierung kurzer Strings.

Für den Huffman-Algorithmus muss der Codierungsbaum mit dem komprimierten Text gesendet werden. Bei einem kleinen Text kann das Ergebnis aufgrund des Baums daher größer als der ursprüngliche Text sein.

4
Benoit Courtine

Die Huffman-Kodierung ist hier eine sinnvolle Option. Gzip und Freunde tun dies, aber die Arbeitsweise besteht darin, einen Huffman-Baum für die Eingabe zu erstellen, diesen zu senden und dann die mit dem Baum verschlüsselten Daten zu senden. Wenn die Baumstruktur relativ zu den Daten groß ist, wird möglicherweise keine Größe gespeichert.

Es kann jedoch vermieden werden, einen Baum zu senden: Stattdessen ordnen Sie dem Sender und dem Empfänger bereits einen Baum zu. Es kann nicht speziell für jeden String erstellt werden, aber Sie können einen einzigen globalen Baum verwenden, um alle Strings zu codieren. Wenn Sie es aus der gleichen Sprache wie die Eingabestrings erstellen (Englisch oder was auch immer), sollten Sie trotzdem eine gute Komprimierung erhalten, wenn auch nicht so gut wie bei einem benutzerdefinierten Baum für jede Eingabe.

4
Tom Anderson

Huffman Coding kann hilfreich sein, aber nur, wenn in Ihrem kleinen String viele häufige Zeichen enthalten sind

4
Noel M

Wenn Sie wissen, dass Ihre Zeichenketten hauptsächlich ASCII sind, können Sie sie in UTF-8 konvertieren.

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

Dies kann die Speichergröße um etwa 50% reduzieren. Sie erhalten jedoch ein Byte-Array und keine Zeichenfolge. Wenn Sie es jedoch in eine Datei schreiben, sollte dies kein Problem sein.

So konvertieren Sie wieder in einen String:

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

Schauen Sie sich den Huffman-Algorithmus an.

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

Die Idee ist, dass jedes Zeichen durch eine Folge von Bits ersetzt wird, abhängig von ihrer Häufigkeit im Text (je häufiger, desto kleiner die Folge). 

Sie können Ihren gesamten Text lesen und eine Codetabelle erstellen, zum Beispiel:

Symbolcode

a 0

s 10

e 110

m 111

Der Algorithmus erstellt basierend auf der Texteingabe einen Symbolbaum. Je mehr Charaktere Sie haben, desto schlechter ist die Komprimierung.

Abhängig von Ihrem Text könnte dies jedoch effektiv sein. 

0
live-love

Die kompakte String-Verbesserung ist in Java 9 https://openjdk.Java.net/jeps/254 sofort verfügbar

Java.lang.String hat jetzt:

privater Endbytewert [];

0
Anurag Sharma

Sie sehen keine Komprimierung für Ihren String. Da Sie mindestens ein paar hundert Byte benötigen, um eine echte Komprimierung mit GZIPOutputStream oder ZIPOutputStream durchzuführen. Ihr String ist zu klein. (Ich verstehe nicht, warum Sie für dieselbe Komprimierung benötigen)

Überprüfen Sie die Schlussfolgerung aus diesem Artikel

Der Artikel zeigt auch, wie komprimiert wird und dekomprimieren Sie Daten im Handumdrehen um den Netzwerkverkehr zu reduzieren und verbessern Sie die Leistung Ihres Client/Server-Anwendungen . Das direkte Komprimieren von Daten jedoch verbessert die Leistung von Client/Server-Anwendungen nur bei die zu komprimierenden Objekte sind mehr als ein paar hundert Bytes. Sie wäre nicht in der Lage zu beobachten Verbesserung der Leistung, wenn die Objekte werden komprimiert und übertragen werden einfache String-Objekte, zum Beispiel.

0
YoK