Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Hex in lesbare Zeichen umwandeln (möglichst kompakt)
baer999
myCSharp.de - Member



Dabei seit:
Beiträge: 375

Themenstarter:

Hex in lesbare Zeichen umwandeln (möglichst kompakt)

beantworten | zitieren | melden

Hallo,

ich möchte gern einen Hex Wert, wie bspw.:

BFEBFBFF000206A7


umwandeln (zwecks Komprimierung), dabei muss aber die Lesbarkeit gewährleistet sein (also keine ASCII Konvertierung, da hier Zeichen enthalten sind, die "nicht lesbar" sind).

Mir würde es reichen, wenn aus dem obigen 16-stelligen Bsp. nach der Umwandlung 10-12 Zeichen übrig bleiben würden.

Hat da jemand eine Idee?

Der Pool für die Zeichen soll alle Buchstaben und alle Zahlen beinhalten.
private Nachricht | Beiträge des Benutzers
Darth Maim
myCSharp.de - Member



Dabei seit:
Beiträge: 216

beantworten | zitieren | melden

Hex String -> Byte[] -> Base64 String

Das würde für dein Beispiel v+v7/wACBqc= (12 Zeichen) ergeben.

Wenn dir das zu unleserlich ist, kannst du auch base32 nehmen (BVQVRVS0041L7, 13 Zeichen).
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo baer999,

es gibt 128-33 = 95 druckbare (7-Bit)ASCII-Zeichen. Also mehr als bei base64 und erst recht base32 verwendet werden. Wenn man einen noch größeren Zeichensatz als 7-bit-ASCII verwenden kann, um so besser. Anderseits sollte man optisch ähnliche Zeichen, z.B. 1 und I oder 0 und O aus dem Zeichenvorrat entfernen. Im Beispiel bezeichne ich die Anzahl der gewählten Zeichen mit N, denn das Verfahren geht mit jeder beliebigen Zahl an Zeichen. Je mehr Zeichen, desto kompakter das Ergebnis.

Du packst alle gewünschten Zeichen in ein Array (die Reihenfolge ist im Prinzip egal). Dann betrachtest du den Hex-String als eine große Hexzahl. Du könntest den Hex-String z.B. in einen BigInteger konvertieren. Dann rechnest du die Zahl modulo N und verwendest das Ergebnis als Index in das Array, um das erste Zeichen zu ermitteln. Dann teilst du die Zahl durch N und rechnest vom Ergebnis wieder Modulo N für das zweite Zeichen und das immer so weiter, bis das Ergebnis des wiederholten Teilens 0 ist. Das ist aus meiner Sicht die kompaktestmögliche Darstellung.

Kompakter kann man m.E. nur werden, wenn man die Eingabe für sich genommen komprimiert, z.B. per ZipStream. Aber die Frage ist, ob der dabei nötige Verwaltungs-Overhead die Ersparnis nicht wieder (mehr als) auffrisst. Die mögliche Ersparnis hängt von der enthaltenen Redundanz ab. Wenig redundante Eingabestrings/-zahlen werden durch die Kompression sogar (etwas) länger.

herbivore
private Nachricht | Beiträge des Benutzers
baer999
myCSharp.de - Member



Dabei seit:
Beiträge: 375

Themenstarter:

beantworten | zitieren | melden

Super Tipps, vielen dank!

Ich habe nun eine Base62 implementiert, habe jedoch noch Probleme bei der Rückrechnung, sieht da jemand, wo ich den logischen Fehler drin habe?

Bsp. war:

ToBase62(311299) => XYi

ABER

FromBase62(XYi) => 230534


Quellcode:

        private string Base62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

        public string ToBase62(Int64 i)
        {
            StringBuilder sb = new StringBuilder();  
            Int64 rest = i;

            while (rest / 62 != 0)
            {
                long index = rest % 62;
                sb.Append(Base62[(int)index]);

                rest = rest / 62;
            }

            return sb.ToString();
        }

        public Int64 FromBase62(String s)
        {
            char[] chrs = s.ToCharArray();
            int m = chrs.Length - 1;
            int n = 62;
            int x;
            int rtn = 0;

            foreach (char c in chrs)
            {
                x = Base62.IndexOf(c);

                rtn += x * (Convert.ToInt32(Math.Pow(n, m)));

                m--;
            }

            return rtn; 
        }

Danke !!!
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von baer999 am .
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo baer999,

du musst die Schleife durchlaufen, solange rest noch nicht Null ist, sonst schluckst du das letzte Zeichen. Ob das der einzige Fehler ist, weiß ich nicht, aber das lässt sich ja leicht im Debugger herausbekommen, siehe [Artikel] Debugger: Wie verwende ich den von Visual Studio?.

Davon abgesehen birgt die Verwendung von Math.Pow das unnötige Risiko von Rundungsfehlern. So wie du in der einen Richtung den Rest sukzessive durch 62 teilst, solltest du in der anderen Richtung das Zwischenergebnis sukzessive mit 62 multiplizieren.

Apropos 62: Das ist nicht gerade DRY. Ich würde eine Konstante verwenden. Oder noch besser Array.Length verwenden. Dann passt die Berechnung immer zu der tatsächlich im Array enthaltenen Anzahl von Zeichen.

herbivore
private Nachricht | Beiträge des Benutzers