vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Mails senden, abrufen und decodieren - ganz easy ;-)  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Fortgeschrittene
Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 04.04.22 13:17

Hi,
ich bekomme von einem Modul einen String mit wirren Binärdaten.
(Leider habe ich keinen Einfluss auf das Datenformat)
Diese Daten sollen komprimiert werden.
Leider klappt das nicht.
Ich habe das Encoding im Verdacht, da ich schonmal an andere Stelle Ärger damit hatte.
Aber ich bastele hier seit Stunden und komme nicht weiter.
Mein Beispielcode braucht nur ein Form mit 3 Textboxen (Multiline) und einen Button:

Public Class Form1
      ' Encoding hier zentral ändern:
      Dim Enco As System.Text.Encoding = System.Text.Encoding.Default
      Private Sub Button1_Click(sender As Object, e As EventArgs) Handles _
        Button1.Click
            Dim Eingabe As String = "Test:  "
            ' Wirre Daten einfüllen:
            For x As Int32 = -32768 To 65535  ' 0 To 127 geht!  
                  Eingabe &= (ChrW(x)) & " "
            Next
            ' Einmal Compressen und Decompressen:
            Dim CompressedText As String = MyCompress(Eingabe)
            Dim Ausgabe As String = MyDecompress(CompressedText)
            'Ausgabe (nur zur Kontrole ...):
            TextBox1.Text = Eingabe
            TextBox2.Text = Ausgabe
            TextBox3.Text = CompressedText
            ' Vergleich (Rot = schlecht ...):
            If Eingabe = Ausgabe Then
                  TextBox2.BackColor = Color.LightGreen
            Else
                  TextBox2.BackColor = Color.LightSalmon
            End If
      End Sub
      Function MyCompress(ByVal str As String) As String
            Dim Erg As String = ""
            Using output As New IO.MemoryStream()
                  Using gzip As New IO.Compression.DeflateStream(output, _
                    IO.Compression.CompressionMode.Compress)
                        Using writer As New IO.StreamWriter(gzip, Enco)
                              writer.Write(str)
                        End Using
                  End Using
                  Erg = Enco.GetString(output.ToArray)
            End Using
            Return Erg
      End Function
      Function MyDecompress(ByVal input As String) As String
            Dim Erg As String = ""
            Using inputStream As New IO.MemoryStream(Enco.GetBytes(input))
                  Using gzip As New IO.Compression.DeflateStream(inputStream, _
                    IO.Compression.CompressionMode.Decompress)
                        Using reader As New IO.StreamReader(gzip, Enco)
                              Erg = reader.ReadToEnd
                        End Using
                  End Using
            End Using
            Return Erg
      End Function
End Class
Bei "Klick" werden Binärdaten generiert, dann einmal komprimiert und DEkomprimiert.
Bei einem anschließenden Vergleich sind die Daten aber unterschiedlich.
Da ich keine Fehlermeldung bekomme und in der "Befüll-Schleife" die normalen ASCII-Werte (0-127) gehen, denke ich an das Encoding. Ich habe inzwischen aber alle üblichen Encodings getestet.
Kennt jemand eine grundsätzlich andere Vorgehensweise?
Oder habe ich da nur etwas verbockt?

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: eierlein
Datum: 04.04.22 14:32

Für ChrW brauchst du Encoding.Unicode.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 04.04.22 14:33

Hi,
dachte ich auch, hilft aber nix.

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Kuno60
Datum: 04.04.22 21:06

Hallo,

gib bei StreamWriter keine Kodierung an, bei Compress und Decompress. Diese wirkt sich sonst auf den komprimierten String aus.

Unicodezeichen werden dann auch wieder richtig hergestellt.

Using writer As New StreamWriter(gzip)
   writer.Write(str)
End Using
 
'Eingabe: 
' "ABCÄÖÜß∑√⌀≠≈⦝↯↑↓"
'Ausgabe: 
' "ABCÄÖÜß∑√⌀≠≈⦝↯↑↓"
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 05.04.22 09:31

Hi,

Kein Encoding angeben?
Ich dachte, dann nimmt er er sowieso "Default".

Aber: Stimmt, das macht einen Unterschied!
Jetzt kommt die Meldung:
Das Unicode-Zeichen \uD800 im Index 7 kann nicht in die angegebene Codepage übersetzt werden.

Bis Charakter D800, also 55296, klappt alles prima.
(Mit Encoding "Default" für GetString und GetBytes)
Ich habe noch nicht getestet, ob es im realen Programm ausreicht, aber das könnte mein Problem lösen.

Trotzdem ist das irgendwie unbefriedigend, wenn es nicht von 0-65535 klappt.
(Wobei ChrW auch negative Werte ab -32768 annimmt, -8192 bis 55295 geht!)

Hat denn niemand sonst das Problem, dass ein String mit Binärdaten komprimiert werden muss?
Gibt es da keine bessere Lösung?

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Kuno60
Datum: 05.04.22 18:11

Hi,

ich habe es auch mit dem Datei-Beispiel getestet, dass bei der DeflateStream-Klasse angegeben ist. Da funktioniert es mit allen Zeichen von -32768 bis 65535, wenn ich bei der Datei UTF8 als Kodierung angebe. Nur dort und nicht bei Compress und Decompress.
  Private Sub CreateFileToCompress()
    File.WriteAllText(OriginalFileName, Message, System.Text.Encoding.UTF8)
  End Sub
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 05.04.22 18:51

Hi,
hast du das mit dem Beispiel von oben getestet?
Denn bei mir läuft das einfach nicht.
Und "File.WriteAllText" suggeriert mir du nutzt eine DATEI?
Ich möchte einen String komprimieren und einen neuen String als Ergebnis.
Daher nützt ein Datei-Beispiel nicht so viel.
Ich habe natürlich auch schon UTF8 getestet, aber ohne Erfolg.

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: eierlein
Datum: 05.04.22 19:22

Zitat:

Kein Encoding angeben?
Ich dachte, dann nimmt er er sowieso "Default".

Kein Encoding bedeutet UTF-8. (Standard-Encoding)


Zitat:

Jetzt kommt die Meldung:
Das Unicode-Zeichen \uD800 im Index 7 kann nicht in die angegebene Codepage übersetzt werden.


D800 ist das erste High-Surrogate-Zeichen und erwartet als Nächstes ein Low-Surrogate-Zeichen.

High-Surrogate -> D800—DB7F
Low-Surrogate -> DC00—DFFF
Mit den Surrogate Paaren können Unicode-Zeichen > 65535 erzeugt werden.

Encoding.Default bedeutet Ansi-Codepage 1252 (bei deutschem Windows).
Das Problem ist, die Zeichen (Dez.) 129, 141, 143, 144, 157 sind nicht belegt.
Bedeutet: Werden durch Fragezeichen ersetzt.

Versuch' mal eine voll belegte DOS Codepage:

Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding(850)
Ansonsten stell eine echte Datei zur Verfügung.

Beitrag wurde zuletzt am 05.04.22 um 19:23:58 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 05.04.22 19:51

Hi,

ich kenne grob die ganze Unicode-Sache.
Vielleicht verstehe ich aber beim "String" was nicht so ganz.

"String" enthielt für mich immer Bytes.
Also, 8Bit Werte.
Wenn dem so ist, sollte die Kompression doch kein Problem sein, EGAL was letzlich aus den Bytes generiert wird. Ob die Bytes dann einzeln als ASCII oder zu zweier oder 4er Grüppchen als UTF8, 16, 32 oder wie auch immer ausgewertet werden ist dem String doch egal. Oder sehe ich da was falsch.

Die Methode "GetBytes" bestätigt eigentlich was ich denke. Aber das was mein Programm macht, scheint ja nicht mehr auf "Bytes" im wahren Sinn anwendbar zu sein, denn dann dürften ja alles nur Werte von 0-255 sein.

Ich habe jedenfalls einen String, der nach kompressen und dekompressen nicht mehr identisch ist.
DAS ist mein Problem.
Ich kann vorher nicht sagen, was der Sting enthält, ich bekomme den nur übergeben.

Es muss doch eine Möglichkeit geben einen Sting zu komprimieren, EGAL was er enthält.

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 06.04.22 16:28

Hallo!

Ein String ist eine Zeichenfolge und wird als eine solche komprimiert.
Der verwendete Zeichen-Code ist entscheidend für die Kompression.
Ansonsten müsstest Du Byte-Folgen komprimieren.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 06.04.22 18:37

Hi,

dann frag' ich nochmal so:
Es muss doch eine Möglichkeit geben einen beliebigen String zu komprimieren, EGAL was er enthält.

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 07.04.22 01:08

Du begreifst es offenbar nicht.
Ein String ist eine Zeichenfolge, also eine Abfolge von Bytes, die über einen Zeichensatz (Codetabelle) erzeugt worden ist. Es ist deshalb nicht EGAL, was er enthält.
Deine Daten bilden anscheinend keinen String, sondern sind aus einem anderen Format entstanden.
In dem Fall kannst Du sinnvollerweise die Bytefolge komprimieren.
Auf die Möglichkeit, eine Ascii-Tabelle zu nútzen, bist Du bereits hingewiesen worden.
Codetabellen enthalten aber auch Steuerzeichen, d.h. bestimmte Byte-Werte werden nicht als Symbol
verarbeitet/gewandelt, sondern sie entsprechen Aktionen (z.B. Zeilenvorschub etc.)

Warum willst Du Deine Bytes unbedingt in eine Zeichenfolge umwandeln?
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 07.04.22 09:47

Hi,

OK, prima, wenn es nicht egal ist was ein String enthält, wo im String wird denn genau festgelegt WAS er enthält? Hat ein String einen "Header"?
Und wie kann ich rausfinden WAS er enthält?

Schließlich programmiere ich eine NEUTRALE Prozedur die einfach einen String übergeben bekommt.
Wie soll das dann gehen das dieser komprimiert wird, wenn ich nie weiß was ich bekomme?

Stimmt, meine Daten sind aus einem anderen Format entstanden. Leider habe ich keinen Schimmer was das für ein Format ist, da ich halt "nur" einen String bekomme. Das kann ich auch nicht ändern, es ist ein externes Modul.
Würde ich eine Bytefolge bekommen, wäre ich nicht hier im Forum mit der Frage.

Ich sehe das eigentliche Problem darin: Wie bekomme ich aus einem UNBEKANNTEN String eine Bytefolge?
Und wie bekomme ich aus der Bytefolge später wieder GENAU DIESEN String.

Eine wirklich neutrale Lösung ist also nicht in Sicht?

Bye,

Dilbert

Nachtrag:
Du schreibst: "Eine String ist eine Bytefolge..."
Jaaa, genau, und wie lese ich die (8-bit) Bytes aus?
Keine D-Words oder 16 Bit Unicodes, die BYTEFOLGE will ich.
Und wieder zurück...

--
while (!asleep()) sheep++;

Beitrag wurde zuletzt am 07.04.22 um 09:52:39 editiert.

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 07.04.22 13:09

Hallo!

Hast Du die GetBytes-Methode probiert (mit verschiedenen Encodings)?

https://www.delftstack.com/de/howto/csharp/how-to-convert-a-string-to-a-byte-array-in-csharp

Was geschieht, wenn Du solche Bytefolgen komprimierst?


Hinweis:
Net.Core unterstützt (zur Zeit?) nicht alle Codepages, die im Net.Framework verwendet werden konnten.
Siehe Dokumentation zur Encoding-Klasse in Namespace System.Text.

Beitrag wurde zuletzt am 07.04.22 um 13:30:43 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 07.04.22 17:15

Hi,
hast du mein Beispiel oben gesehen?
Gleich oben in der "MyDecompress" mache ich das.
Was mir aber gerade auffällt:
Ich mache das nicht in der MyCompress...
Dort wird der String einfach mit den "writer.Write" geschrieben...
Hmmm, da muss ich noch mal drüber schauen.
Leider hab' ich heute und morgen kaum Zeit, aber das könnte ein Lichtblick sein...

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Kuno60
Datum: 07.04.22 19:27

Hi Dilbert,

du hast noch nicht verstanden, dass ein String keine Bytefolge ist.

Ich fasse noch mal zusammen:

Eine Zeichenfolge (String) ist eine Folge von 16-Bit-Unicode-Zeichen (Char).
Die DeflateStream-Klasse kann aber nur eine Bytefolge verarbeiten.
Deshalb kann eine Zeichenfolge nicht direkt komprimiert werden und muss erst in ein Byte-Array umgewandelt werden. Das beste Ergebnis erhält man mit UTF-8, da da fast alle Zeichen in einzelne Bytes umgewandelt werden. Sonderzeichen belegen mehrere Bytes.
Werden nun diese Bytes komprimiert, so erhält man ein kleineres Byte-Array.
Dieses komprimierte Byte-Array kann dann dekomprimiert werden und wieder in eine Zeichenfolge umgewandelt werden.

Das originale Byte-Array stimmt exakt mit dem dekomprimierten Byte-Array überein!
Doch nach der Umwandlung in eine Zeichenfolge, werden nicht alle Zeichen exakt wiederhergestellt. Den Grund dafür hat "eierlein" bereits genannt. Das dürfte aber kein Problem sein, da in deinem externen Modul die Zeichen sicher nicht mit ChrW() erzeugt werden.

In deinem Beispiel wandelst du die komprimierten Bytes wieder in einen String um. Das geht zwar, macht aber nicht viel Sinn, da dabei nur wirres Zeug raus kommt (wegen binärer Daten).

Hier mein Test mit Bytes:

Imports System.IO
Imports System.IO.Compression
Imports System.Text
 
Module Module2
 
  Sub MeinTest()
    Dim sb As New StringBuilder
    For x = -32768 To 65535
      sb.Append(ChrW(x))
    Next
    Dim Eingabe As String = sb.ToString
 
    Dim OrigBytes As Byte() = Encoding.UTF8.GetBytes(Eingabe)
    Dim ComprBytes As Byte() = Compress(OrigBytes)
    Dim DecomprBytes As Byte() = Decompress(ComprBytes)
    Dim Ausgabe As String = Encoding.UTF8.GetString(DecomprBytes)
 
    Console.WriteLine("Länge Eingabe: {0}", Eingabe.Length)
    Console.WriteLine("Länge Ausgabe: {0}", Ausgabe.Length)
    Console.WriteLine()
    Console.WriteLine("Länge original Bytes: {0}", OrigBytes.Length)
    Console.WriteLine("Länge komprimierte Bytes: {0}", ComprBytes.Length)
    Console.WriteLine("Länge dekomprimierte Bytes: {0}", DecomprBytes.Length)
    Console.WriteLine()
    Console.WriteLine("Gleiche Bytes: {0}", OrigBytes.SequenceEqual( _
      DecomprBytes))
    Console.WriteLine("Gleicher Text: {0}", Eingabe = Ausgabe)
  End Sub
 
  Function Compress(ba As Byte()) As Byte()
    Using input As New MemoryStream(ba)
      Using output As New MemoryStream()
        Using gzip As New DeflateStream(output, CompressionMode.Compress)
          input.CopyTo(gzip)
        End Using
        Return output.ToArray
      End Using
    End Using
  End Function
 
  Function Decompress(ba As Byte()) As Byte()
    Using input As New MemoryStream(ba)
      Using output As New MemoryStream()
        Using gzip As New DeflateStream(input, CompressionMode.Decompress)
          gzip.CopyTo(output)
          Return output.ToArray
        End Using
      End Using
    End Using
  End Function
 
End Module
Ausgegebener Text:

Länge Eingabe: 98304
Länge Ausgabe: 98304

Länge original Bytes: 292732
Länge komprimierte Bytes: 185853
Länge dekomprimierte Bytes: 292732

Gleiche Bytes: True
Gleicher Text: False
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 07.04.22 20:05

Hi,

also eurer Aussage nach ist es nicht möglich einen BELIEBIGEN String so zu komprimieren, dass ein StringVorher=StringNacher geht?!?

Bye

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 10.04.22 11:35

Hi,

ist so still geworden?
Nochmal die Frage:

Kann mir jemand bestätigen, dass es (ohne zu wissen was der String enthält!) nicht möglich ist,
einen String so zu komprimieren, dass nach dem Dekompress "StringVorher = StringNacher" ist?

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 10.04.22 15:25

Hallo!

Was ist mit Dir los?
Stringvariablen enthalten Zeichenfolgen, die über einen Code erzeugt werden,
der die Beziehung zwischen Zeichen und Bytes definiert.
Alle Methoden für String-Variablen setzen einen Code voraus und wenden
den angegebenen Code in ihrer Funktionalität an.

Wenn in einer Stringvariable eine "unklare Bytefolge" steht,
können diese String-Methoden nicht sinnvoll operieren.
Falls String-Funktionen in dem Fall ein Ergebnis liefern, sind "Zeichen"
(Bytemuster)eventuell nicht eindeutig definiert gewesen und deshalb
bei Anwendung der Funktion ersetzt worden.

Ohne sehr viel genauere Angaben, kann man Dir sonst nichts sagen.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: eierlein
Datum: 10.04.22 17:32

Teste den Code außer mit den Test-Bytes, mit beliebigen Dateien
Ansonsten siehe:
https://docs.microsoft.com/de-de/dotnet/api/system.io.compression.gzipstream?view=net-6.0

Option Explicit On
Option Strict On
 
Imports System.Text
Imports System.IO
Imports System.IO.Compression
 
 
Module Module1
 
    Sub Main()
        Dim Enco As System.Text.Encoding = System.Text.Encoding.GetEncoding(850)
        '------------------------------------------------------------
        'Test-Bytes erzeugen.  Immer von 00 bis FF 
        Dim b(999999) As Byte
        Dim y As Integer = 0
        For i As Integer = 0 To 999999
            y += 1
            If y > 255 Then y = 0
            b(i) = CByte(y)
        Next
 
        '----------------------------------------------------------------------
        ' -----
        'Entweder  TestBytes ###################################
        ' Dim OrigBytes As Byte() = b  'TestBytes --> b
 
        'Oder  Datei einlesen ################################
        Dim t() As Byte = IO.File.ReadAllBytes("D:\#x\1.csv") ' -> Pfad anpassen
 
        Dim OrigBytes As Byte() = t   '' Datei  ---> t
        '----------------------------------------------------------------------
        ' -------
 
        Dim ComprBytes As Byte() = Compress(OrigBytes)
        Dim DecomprBytes As Byte() = Decompress(ComprBytes)
        '----------------------------------------------------------------------
        ' -------
        'Falls Strings gebraucht werden:
        Dim Eingabe As String = Enco.GetString(OrigBytes)
        Dim Ausgabe As String = Enco.GetString(DecomprBytes)
        Dim CompString As String = Enco.GetString(ComprBytes)
        '----------------------------------------------------------------------
        ' -------
        'Decompriemierte Datei Schreiben -> Pfad anpassen
        IO.File.WriteAllBytes("d:\#x\bin_default.dat", DecomprBytes)
 
        '----------------------------------------------------------------------
        ' -------
        Console.WriteLine("Länge Eingabe: {0}", OrigBytes.Length)
        Console.WriteLine("Länge Ausgabe: {0}", DecomprBytes.Length)
        Console.WriteLine()
        Console.WriteLine("Länge original Bytes: {0}", OrigBytes.Length)
        Console.WriteLine("Länge komprimierte Bytes: {0}", ComprBytes.Length)
        Console.WriteLine("Länge dekomprimierte Bytes: {0}", _
          DecomprBytes.Length)
        Console.WriteLine()
        Console.WriteLine("Gleiche Bytes: {0}", OrigBytes.SequenceEqual( _
          DecomprBytes))
        Console.WriteLine("Gleicher Text: {0}", Eingabe = Ausgabe)
        Console.WriteLine("Länge Eingabe: " & Eingabe.Length.ToString)
        Console.WriteLine("Länge Ausgabe: " & Ausgabe.Length.ToString)
        Console.Read()
    End Sub
 
    Function Compress(ba As Byte()) As Byte()
        Using input As New MemoryStream(ba)
            Using output As New MemoryStream()
                Using gzip As New DeflateStream(output, _
                  CompressionMode.Compress)
                    input.CopyTo(gzip)
                End Using
                Return output.ToArray
            End Using
        End Using
    End Function
 
    Function Decompress(ba As Byte()) As Byte()
        Using input As New MemoryStream(ba)
            Using output As New MemoryStream()
                Using gzip As New DeflateStream(input, _
                  CompressionMode.Decompress)
                    gzip.CopyTo(output)
                    Return output.ToArray
                End Using
            End Using
        End Using
    End Function
 
End Module
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 10.04.22 18:40

Hi Manfred,

was mit mir los ist?
Was ist das für 'ne Frage?!?

Ein weiteres mal mein Problem:
Ich bekomme von einem anderen Programmteil (Auf den ich keinen Einfluss habe!)
einen String.
Diesen muss ich komprimieren.
Wenn das Hauptprogramm danach fragt, muss ich den vorher komprimierten String wieder 1:1 zurückgeben.

Also laut Manfred geht das nicht. Werd' ich meinem Chef so sagen ...
Und das Beispiel von eierlein macht das ganze mit ByteArrays. Prima, aber das wusste ich schon.
Durch eierlein wurde mir aber klar, man kann das Problem auf "String->Byte" und zurück eingrenzen
und die Kompression dabei erstmal ganz außer acht lassen.

Also neu formulierte Frage:
Lässt sich ein String mit UNBEKANNTEM INHALT in ein Bytearray und zurück in einen identischen
String wandeln?

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: eierlein
Datum: 10.04.22 19:07

Lässt sich ein String mit UNBEKANNTEM INHALT in ein Bytearray und zurück in einen identischen
String wandeln?



Im Prinzip Ja.

Frage: Wie kommt der String in dein Programm?
Hast du einen Beispielstring?
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 10.04.22 21:28

Hi,

den String bekomme ich in mein Modul übergeben. Keine Ahnung wie der generiert wird.
Als BeispielString nutze ich im Moment das:

Dim Eingabe As String = "Test:  "
For x As Int32 = -32768 To 65535  ' 0 To 127 geht!  
Eingabe &= (ChrW(x)) & " "
Next
Das hat sich bisher bewährt.
WichDich:
Das Leerzeichen jeweils mit anhängen.
Und keinen Stringbuilder nutzen, den hatte ich erst auch, damit hat es geklappt, aber ohne StingBuilder plötzlich nicht mehr. Warum das so ist wäre dann die nächste Frage. Aber bitte nicht in diesen Thread mischen...

Wenn das komprimieren geht, sollte auch der übergebene String gehen.

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 11.04.22 16:27

Hallo!

Ein Ansatz:
Zähle durch wie viele verschiedene "Zeichen" in diesem "String" stehen.
Sind es maximal 255 benutze den Typ Byte, sonst Short.
Ordne jedem "Zeichen" jeweils einen Zahlenwert zu (=bitmuster) und
komprimiere diese Folge binär.
Diese selbst erstellte "Codetabelle" enthält keine Voraussetzungen
und Einschränkungen, wie sie bei String-Codecs vorkommen.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 11.04.22 20:35

Hi,

du meinst ein Dictionary (of char,int) oder sowas?
Und wie lese ich das "Zeichen" aus dem String?
Wenn ich das rausschneide brauch' ich doch wieder 'ne (De-)Codierung?
Per Substring() und dann mit Strings.Asc oder Strings.AscW könnte klappen.
Aber da müsste ich ja wiederum schauen ob Asc oder AscW?
Hmmm, da muss ich mal ein bisschen mit experimentieren.

Bye, Dilbert
P.S.:
Dann muss ich das Dictionary ja zusammen mit dem komprimierten
String speichern, da ja jeder String ein anderes Dict bekommt.
Das bläht die Kompression ja wieder riesig auf!
So wird das nix.

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Vorschlag für Umwandlung der Zeichenfolgen in Bytefolgen 
Autor: Manfred X
Datum: 11.04.22 22:04

Probier mal so etwas (ohne Stringoperationen)

  'angenommen dies seien Deine komischen Stringvariablen
  Dim a As String = "asdasdfdfße5045ß6945"
  Dim b As String = "2@²&//0---.... wewerw"
  Dim c As String = "éüä'''##+*+~~à"
 
  '.... zusammengefasst in einer Liste 
  Dim mydata As New List(Of String)
  mydata.Add(a) : mydata.Add(b) : mydata.Add(c)
 
  'Erstellung der Code-Tabelle aus den String-Zeichen
  Dim codetable As New List(Of Char)
  For Each serie As String In mydata
     For i = 0 To serie.Length - 1
         If Not codetable.Contains(serie(i)) Then codetable.Add(serie(i))
     Next i
  Next serie
 
  'Umwandlung der Strings jeweils in eine Liste von Bytefolgen
  Dim myCodeSeries As New List(Of List(Of Byte))
  Dim bytes() As Byte
  Dim cnt As Integer = -1
 
  For Each serie As String In mydata
      myCodeSeries.Add(New List(Of Byte))
      cnt += 1
      For i As Integer = 0 To serie.Length - 1
          'Die Codetabelle liefert den Ushort-Wert des Zeichens, 
          'der Bitconverter die beiden entsprechenden Bytes
          bytes = BitConverter.GetBytes(CUShort(codetable.IndexOf(serie(i))))
          myCodeSeries(cnt).Add(bytes(0))
          myCodeSeries(cnt).Add(bytes(1))
      Next i
  Next serie
 
 
  'Diese Bytefolgen können jetzt komprimiert werden
  '------------------------------------------------
 
  'Zurückverwandlung der dekomprimierten Byteserien in das Ausgangsmaterial
 
  Dim mydata2 As New List(Of String)
  cnt = -1
 
  For Each codeserie As List(Of Byte) In myCodeSeries
      cnt += 1
      mydata2.Add("")
      For i As Integer = 0 To codeserie.Count - 1 Step 2
         'Bitconvertert liefert Ushort-Wert zu den 2 Bytes, die Codetable das 
         ' Zeichen
         mydata2(cnt) &= 
         codetable(BitConverter.ToUInt16(New Byte() {codeserie(i), codeserie(i _
           + 1)}))
      Next i
  Next codeserie
 
 
  'Kontrolle  
  For i As Integer = 0 To mydata.Count - 1
      For k As Integer = 0 To mydata(i).Length - 1
          If mydata(i)(k) <> mydata2(i)(k) Then Stop
      Next k
  Next i


Beitrag wurde zuletzt am 11.04.22 um 22:31:18 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 11.04.22 23:03

Hi,

jaaaa, das klappt, aber:
Ich habe den Code mal drastisch vereinfacht, die "List(of List(..." Sache brauche ich nicht.
Außerdem meinen Beispiel-String-Generator wieder eingebaut. Wenn der klappt, klappt alles

So gehts erstmal:
            Dim Eingabe As String = "Test:  "
            For x As Int32 = -32768 To 65535
                  Eingabe &= (ChrW(x)) & " "
            Next
 
            'Erstellung der Code-Tabelle
            Dim codetable As New List(Of Char)
            For i As Int32 = 0 To Eingabe.Length - 1
                  If Not codetable.Contains(Eingabe(i)) Then codetable.Add( _
                    Eingabe(i))
            Next i
 
            'Umwandlung in eine List von Bytefolgen
            Dim myCodeSeries As New List(Of Byte)
            Dim bytes() As Byte
            For i As Integer = 0 To Eingabe.Length - 1
                  bytes = BitConverter.GetBytes(CUShort(codetable.IndexOf( _
                    Eingabe(i))))
                  myCodeSeries.Add(bytes(0))
                  myCodeSeries.Add(bytes(1))
            Next i
 
            'Zurückwandeln der Bytefolgen in String
            Dim Zurück As String = ""
            For i As Integer = 0 To myCodeSeries.Count - 1 Step 2
                  Zurück &= codetable(BitConverter.ToUInt16(New Byte() _
                    {myCodeSeries(i), myCodeSeries(i + 1)}, 0))
            Next i
 
            'Kontrolle  
            If Eingabe <> Zurück Then Stop Else MsgBox("OK")
Jetzt das Aber:
Wie ich oben schon befürchtet hatte, muss ich diesen CodeTable für jeden einzelnen String mit speichern.
Das führt die Kompression ad absurdum...
Zumindest für kleinere Stringlängen.

Heute Abend krieg ich das nicht mehr rund, aber ich schau mir das morgen nochmal genauer an...

In diesem Sinne: sheep++
Bye, Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 11.04.22 23:19

Hi,

doch noch keine sheeps gezählt:
Hat denn noch keiner an AscW gedacht?
Das verarbeitet doch 16 Bit Werte!
Scheinbar OHNE CODIERUNG!
Damit geht das erstmal!!!

            Dim Eingabe As String = "Test:  "
            For x As Int32 = -32768 To 65535
                  Eingabe &= (ChrW(x)) & " "
            Next
 
            'Umwandlung in eine List von Bytefolgen
            Dim myCodeSeries As New List(Of Byte)
            Dim bytes() As Byte
            For i As Integer = 0 To Eingabe.Length - 1
                  bytes = BitConverter.GetBytes(AscW(Eingabe(i)))
                  myCodeSeries.Add(bytes(0))
                  myCodeSeries.Add(bytes(1))
            Next i
 
            'Zurückwandeln der Bytefolgen in String
            Dim Zurück As String = ""
            For i As Integer = 0 To myCodeSeries.Count - 1 Step 2
                  Zurück &= ChrW(BitConverter.ToUInt16(New Byte() {myCodeSeries( _
                    i), myCodeSeries(i + 1)}, 0))
            Next i
 
            'Kontrolle  
            If Eingabe <> Zurück Then Stop Else MsgBox("OK")
Soweit suuper, es geht.
Ich spare die ganze CodeTable usw.
Der Haken ist jetzt nur noch, dass es händisch Char für Char durchgehen muss
und daher nicht gerade schnell ist.
Vielleicht kann man das noch "Performance-Optimieren"
Da meine Strings nich so riesig sind, könnte ich erstmal damit leben.

Jetzt aber gute Nacht,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 11.04.22 23:59

Du bist schon wieder auf dem Holzweg.
Du sollst alle Deine Strings nach den enthaltenen Zeichen durchsuchen
um den gesamten Zeichenvorrat zu finden - wie im Code per String-Liste gezeigt.
Dieser allgemeine Zeichenvorrat wird nicht gespeichert, sondern z.B. in einem Modul als
Zeichen-Array hinterlegt, das über eine Readonly-Property oder Methode abgefragt
und für die Komprimierung bzw. Dekomprimierung - wie gezeigt - genutzt werden
kann.
Andere Methoden sind nur bedingt zuverlässig, weil sie auf Annahmen beruhen
die eventuell nicht zutreffen müssen.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 12.04.22 01:12

AscW liefert den Unicode-Wert (2 Byte), der dem entsprechenden Zeichen zugeordnet ist.
Dieser Wert wird als Integer (Int32) zurückgegeben. Das ist fürs Komprimieren nicht besonders
effektiv. Eine Umwandlung in UShort ist zweckmäßig.
Das macht m.E. für das Komprimieren nur Sinn, wenn der Zeichenvorrat auch entsprechend groß ist.
Sonst verteilen sich die Zeichen eventuell ungünstig im Zahlenraum.
Wie stark sich das bei Zeichenmengen von ca. 1000 Zeichen auswirkt, habe ich nicht getestet.


AscW ist die Umkehrfunktion von ChrW.

Beitrag wurde zuletzt am 12.04.22 um 01:17:53 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 12.04.22 11:11

Hi,

ich denke ich bin nicht auf dem Holzweg.
Meine Strings nach dem Zeichenvorrat durchsuchen?
Die ändern sich ja ständig und enthalten teilweise Binärdaten.
Anders ausgedrückt:
Dein "Zeichenvorrat" beträgt mit der Zeit 65536.

Das ASCW die Umkehrung von CHRW ist ist mir auch klar,
so bin ich ja darauf gekommen die zu nutzen.

Eine Umwandlung in UShort ist überflüssig, da ich bei
BitConverter.GetBytes ja nur die Bytes 0 und 1 nutze.
(Ob die Performance besser wird wenn ich es erst in UShort
wandele bezweifele ich, wäre natürlich einen Versuch wert)

Durch diesen Thread habe ich aber gelernt, dass "String"
IMMER und grundsäzlich 2 Byte pro Zeichen speichert.
Es gibt intern keine Codierung.
Die ganze Codierung mit ASC/UTF/... passiert nur beim
Reinschreiben und beim Auslesen, dem String ist das egal.
CHRW und ASCW schreiben die Daten OHNE CODIERUNG direkt
als Zahlenwerte, genau so wie ich das brauche.
(Woher soll ein String auch wissen wie er codiert ist?
Das machen die Routinen, die ihn befüllen.
Oder wie der Ferengi sagt:
Ein String ist ein String ist ein String...)

Außerdem habe ich mir den Speicher mal genau angeschaut
und festgestellt, das CHRW die negativen Zahlen 1:1 in den
Bereich von 32768 bis 65536 mapt.
Das hat den Vorteil, dass ich UInt16 oder Int16
gleichwertig nutzen kann. Das mag manchmal praktisch sein.
ASCW gibt sowieso Int32 zurück, also den positiven Wert.

Bis dahin habe ich mein Programm auch mit realen Daten
gestestet und alles klappt (erstmalig!) ohne Probleme.

Jetzt bleibt die Frage im Raum:
Ist das "manuelle" Durchlaufen des Strings nötig?
Gibt es dafür keine effizientere Vorgehensweise?
Insgesamt wird das bei größeren Datenmengen echt lahm.
Ich weiß, Basic ist kein C, aber schon meine simpelsten
C-Compiler mit abgespecktem Umfang für die kleinen
PIC-Prozessoren können sowas besser!
Einen String aus dem Speicher einfach in eine Bytefolge
konvertieren kann doch nicht so aufwändig sein.
OK, C ist ja auch "Maschinennäher" und dotnet ist für sowas
auch nicht wirklich ausgelegt, aber gibt es da keine
bessere Möglichkeit?

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 12.04.22 13:54

Ich gebe es auf.
JEDE String-Operation beruht auf einem Zeichencode -
AscW nutzt natürlich Unicode.
Dein String enthält irgendein unbekanntes Format in binärer
Form. Zwei Welten!


Du machst:
System.Text.Encoding.Unicode.GetBytes(str)


Beitrag wurde zuletzt am 12.04.22 um 14:04:19 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 12.04.22 15:00

Hi.

Nö, stimmt nicht.
In Unicode sind leider nicht allen Zeichen Codes zugeordnet, genau das war mein Problem.
ChrW und AscW haben für ALLE Zeichen passende Codes.
Genaugenommen wird dort keine Codetabelle verwendet, sondern die übergebenen
Binärwerte 1:1 in den Stringgeschrieben.

Wenn man das beim Auslesen natürlich als Unicode interpretiert
(so wie ich das zuerst hatte) wird das halt nix.

Die Diskussion sollte aber eher in Richtung
"geht sowas auch einfacher"
gehen.

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 12.04.22 15:54

Das ist Unicode.

   Dim enc As System.Text.Encoding = System.Text.Encoding.Unicode
   Dim bytes1() As Byte
   Dim bytes2() As Byte
   Dim index As Integer = -1
 
   Do
       index += 1
 
       bytes1 = enc.GetBytes(index.ToString)  'Encoder
       bytes2 = BitConverter.GetBytes(AscW(index.ToString)) 'AscW
 
       If bytes1(0) <> bytes2(0) Then Stop
       If bytes1(1) <> bytes2(1) Then Stop
   Loop While Index < UShort.maxvalue
Verwende den Unicode-Encoder.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 12.04.22 16:43

Das ist der maximal in einem Framework-String verfügbare Zeichensatz:
        Dim enc As System.Text.Encoding = System.Text.Encoding.Unicode
        Dim bytes1() As Byte
        Dim bytes2() As Byte
        Dim index As Integer = -1
 
        Do
            index += 1
 
            bytes1 = enc.GetBytes(ChrW(index))
            bytes2 = BitConverter.GetBytes(AscW(ChrW(index)))
 
            If bytes1(0) <> bytes2(0) Then Stop
            If bytes2(1) <> bytes2(1) Then Stop
        Loop While index < 55295
Bei höheren Werten liefert AscW die entsprechende Zahl.
Die kann aber nicht in einem String als Zeichen vorkommen.

Beitrag wurde zuletzt am 12.04.22 um 16:45:45 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 12.04.22 17:59

Hi,

warum hat dann das Beispiel oben mit Unicode nicht geklappt?
Ist mir aber auch egal, denn so klappt es jetzt.
Schneller dürfte ASCW auf jeden Fall sein.

Aber die Antwort auf "geht das noch schneller/einfacher" steht noch aus.
Naja, in 'ner Schleife da rum laufen ist zwar nicht gerade schwer,
ich finde das aber unelegant.
Gibt es nicht einfach die Möglichkeit diese Werte in ein ByteArray
zu konvertieren?
Schließlich liegt das intern doch schon als Bytefolge vor?
Hast du dazu 'ne Idee?

Bye, Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 12.04.22 19:30

AscW und Unicode-Encoding unterscheiden sich nicht.
Nach wie vor lieferst Du keine sinnvollen Angeben zu Deinen "Strings"
Wie lang sind diese Folgen?
Wie viele unterscheidbare Zeichen enthalten sie?
Liefert UnicodeEncoding irgendwelche Fehlermeldungen?

 Dim enc1 As New System.Text.UnicodeEncoding(False, True, True)
 Dim bytes as Byte() = enc1.GetBytes("......")
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 12.04.22 20:48

Hi,

hattest du nicht geschrieben du gibst auf?


Aber wenn's dir Freude macht:
Ein letztes mal, DAS ist (immer noch) mein String:

Dim Eingabe As String = "Test:  "
For x As Int32 = 0 To 65535
Eingabe &= (ChrW(x)) & " "
Next
Komprimiere den so, dass das komprimierte Ergebnis wiederum in einem String steht.
(Das will das Hauptprogramm nun mal so und ist nicht zu diskutieren.
Jedenfalls diskutiere ICH nicht mit dem Chef)
Wenn du das dann dekomprimierst will ich wieder 1:1 den ersten Sting bekommen.
Und zwar so dass Originalstring=DekomprimierterString True ergibt.

Aber das hatte ich ja jetzt alles schon 1000 mal geschrieben.
Das es geht und unabhängig vom Inhalt des Strings ist(!) habe ich bewiesen.
Denn eine relativ(!) einfache Lösung hab' ich ja bereits gefunden.
(Siehe wiederum weiter oben...)

Die Frage war nur noch "Geht es NOCH einfacher" und "Geht es schneller".
(Auch das habe ich schon x mal geschrieben)
Falls ja, dann bringt doch einfach ein Beispiel das funktioniert.
MEIN Beispiel steht als Ausgangspunkt (mal wieder) oben.
Siehe 11.04.22 23:19

Bye, Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 12.04.22 21:38

Was Du da hast, ist kein String.
Wenn Du Dir die Mühe machen würdest,
einmal anzuschauen, was da produziert wird,
könntest Du es sehen.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 12.04.22 22:33

OK, damit klinke ich mich hier aus.
Vielen Dank an alle die mir weitergeholfen haben.

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Kuno60
Datum: 13.04.22 11:43

Hi,
klar kann man einen beliebigen String mit der Encoding-Klasse wiederherstellen, aber nur wenn er aus gültigen Zeichen besteht. Alle Unicode Encodings (UTF-8, UTF-16, UTF-32) stellen die Unicodezeichen korrekt wieder her. Mit deiner Schleife erzeugst du aber 2048 ungültige Zeichen, die dann von den Encodings in das Zeichen FFFD "�"c umgewandelt werden, damit ein gültiger String entsteht. Die 1024 Surrogate-Zeichen, die aus 2 Char bestehen, können z.B. mit Char.ConvertFromUtf32() erzeugt werden.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 13.04.22 12:52

Hi Kuno,

genau!
@Manfred:
Du sagst also DAS ist kein String:

Dim Eingabe As String = "Test:  "
For x As Int32 = 0 To 65535
Eingabe &= (ChrW(x)) & " "
Next
LOL

Wie Kuno sagt:
Der String enthält nicht nur gültige Unicode-Zeichen.
DAS kommt der Sache näher.
Da ChrW halt OHNE Unicode-Convertierung alles reinschreibt,
auch ungültige Zeichen, entspricht ChrW eben NICHT dem Unicode!
(Deswegen ist ein String aber immernoch ein String.)
Deine Aussage ich würde Unicode da rein schreiben ist Quatsch.
Ich schreibe halt auch "nicht-Unicode-Zeichen" da rein.
Und das ist eben das Problem.

So lange keiner eine bessere Idee hat als das in einer Schleife
zu durchlaufen und mit AscW wieder auszulesen werde ich mich hier ausklinken.
(OK, das hatte ich schon im letzten Post versprochen )

Bye, Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 13.04.22 17:05

Hallo!

Du verstehst die Zusammenhänge nicht.
Die Methoden Strings.ChrW und Strings.AscW im Namespace Microsoft.Visualbasic
sind aus Gründen der Kompatibilität mit VB6 in Net/Core enthalten.
Sie verarbeiten Zeichen, die in Unicode keiner Kategorie zugeordnet sind.
In VB6 operieren sie mit dem Datentyp Long (32Bit) für Codes und bilden
in solchen Fällen keine einfache Umkehrfunktionen / Bytevertauschung?

Definition von String in VB.Net:
"Enthält Sequenzen von 16-Bit-Codepunkten ohne Vorzeichen (2 Byte),
die zwischen 0 und 65535 liegen.
Jeder Codepunkt oder Zeichencode stellt ein einzelnes Unicode-Zeichen dar".

Hinweis zu System.String (Dokumnetation):
"Beachten Sie, dass es in String-Variablen möglich ist, ein String-Objekt zu erstellen,
das keine wohlgeformte Unicode-Zeichenfolge ist, da eine Instanz aus einer
sequenziellen Auflistung von UTF-16-Codeeinheiten besteht. ....
Obwohl einige Methoden, z. B. die Methoden zum Codieren und Decodieren von
Objekten im System.Text-Namespace, Überprüfungen durchführen können, um
sicherzustellen, dass Zeichenfolgen wohlgeformt sind, stellen String-Klassenmember
nicht sicher, dass eine Zeichenfolge wohlgeformt ist. ....
.NET verwaltet eine eigene Tabelle von Zeichen und entsprechenden Kategorien.
Dadurch wird sichergestellt, dass eine bestimmte Version einer .NET-Implementierung,
die auf unterschiedlichen Plattformen ausgeführt wird, identische Informationen
zu Zeichenkategorien zurück gibt."

Nicht wohlgeformte Character in einer String-Variable sind der Unicode-Kategorie
"OtherNotAssigned" zugeordnet.
Es ist deshalb genau zu unterscheiden zwischen dem Inhalt einer String-Variable und
einer Zeichenfolge. Zeichen besitzen eine Bedeutung.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Kuno60
Datum: 14.04.22 12:34

Es geht hier nur um den Surrogate-Bereich, das sind 2048 Werte von D800 bis DFFF. Dieser Bereich wird genutzt für 21-Bit-Zeichen, die aus 2 Chars bestehen. Diese können auch mit ChrW erzeugt werden, wenn diese Regel befolgt wird: Auf ein High-Surrogate-Zeichen muss ein Low-Surrogate-Zeichen folgen! Ansonsten ist das Zeichen ungültig. Alle anderen UShort-Werte sind gültig.
ChrW() ruft nur die Convert-Klasse auf, ist also dasselbe wie Convert.ToChar(). Das gleiche gilt für AscW().

@Dilbert:
Über Code-Optimierung musst du noch einiges lernen.
Wenn ich einen String mit 2 Millionen zufällig erzeugten Zeichen (auch ungültige) in ein Byte-Array umwandle, dann komprimiere, dann dekomprimiere und wieder in einen String umwandle, dauert das 0,1 Sekunden.

Rate mal, warum ich für die Zeichenerzeugung den StringBuilder verwendet habe...? Manche Leute haben viel Zeit...
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 14.04.22 18:16

Hi,

wenn du mit Optimierung den Stringbuilder meinst?
Ich hatte das (wie bereits oben geschrieben!) als Stringbuilder. Scheinbar wandelt ein Stringbuilder aber die "ungültigen" Zeichen um. Das darf bei meinem Fall (wie inzwichen zur genüge diskutiert!) ja nicht sein. Was genau dort passiert ist mir egal, denn ich bekomme später einen fertigen String, hier geht es ja nur um die Erzeugung eines Beispiels, das ist für "Optimierung" des Codes erstmal völlig unrelevant.
Ich arbeite ich viel mit PIC Prozessoren (12F509 u.ä.), zum Teil in Assembler, meistens in C und C++, DA kannst du lernen was optimieren bedeutet! Bei Taktgeschwindigkeite von 4 MHz und zum Teil 1K Programspeicher 41 Byte(!) Ram kannst du optimieren! Über eine spezielle Schnittstelle eines solchen Prozessors kommt übrigens der String. Und: NEIN, daran lässt sich nichts ändern.

Hat noch jemand was KONSTRUKTIVES beizutragen?
Ich wäre für Tipps die sowas optimieren dankbar:

For i As int32= 0 To Eingabe.Length - 1
   bytes = BitConverter.GetBytes(AscW(Eingabe(i)))
   myCodeSeries.Add(bytes(0))
   myCodeSeries.Add(bytes(1))
Next
Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 14.04.22 19:05

Hallo!

Die in Unicode nicht zugeordneten Byte-Werte bilden keine "Zeichen" und
sie haben deshalb in einer Zeichenfolge nichts zu suchen.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 14.04.22 21:22

Wie weit willst Du gehen?
Du könntest zu C++ wechseln und testen, was Du dort als
Übergabe aus dieser Schnittstelle erhälst.
Die in irgendein Objekt gepackte Bytefolge wäre eventuell
in einen "fixierten Speicherbereich" (=keine Net-Verwaltung)
zu kopieren und dort durch ein Byte-Array direkt zu
überlagern (Zeiger-Operationen).

Eventuell kann man das Marshalling nutzen, um eine Bytefolge zu erhalten.
https://docs.microsoft.com/de-de/dotnet/framework/interop/default-marshalling-for-strings

https://docs.microsoft.com/de-de/dotnet/framework/interop/copying-and-pinning

Beitrag wurde zuletzt am 14.04.22 um 21:32:19 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Marshal String zu Bytearray 
Autor: Manfred X
Datum: 14.04.22 23:59

 
 Private Function StringToBytearray(ByVal str As String) As Byte()
 
        Dim buffersize As Integer = str.Length * 2
        Dim bytearray(buffersize - 1) As Byte
        Dim Handle As IntPtr
        Try
            Handle = Marshal.StringToBSTR(str)
            Marshal.Copy(Handle, bytearray, 0, buffersize)
        Finally
            Marshal.FreeBSTR(Handle)
        End Try
 
        Return bytearray
    End Function
Beispiel:
  Dim test As String = ""
  For i As Integer = 0 To UShort.MaxValue
      test &= ChrW(i)   
  Next i
 
 
  Dim byt As Byte() = StringToBytearray(test)
 
  'Check
  For i As Integer = 0 To byt.Length - 1 Step 2
      Dim bt() As Byte = BitConverter.GetBytes(AscW(test(i \ 2)))
      If byt(i) <> bt(0) Then Stop
      If byt(i + 1) <> bt(1) Then Stop
  Next i
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 15.04.22 20:48

Hi,

juchhu, endlich ist die Zeichen/String Diskussion um und es wird interessant.

Das sieht ziemlich gut aus. Ich habe die nächsten Tage nicht ganz so viel Zeit,
aber so in etwa habe ich mir das vorgestellt.
Ich werde es so bald ich kann testen.
SUPER!
Nicht ganz so "einfach" wie ich dachte, aber ich find's trotzdem recht elegant
und vor allem sollte es deutlich schneller sein.
Nur den "Rückweg" stelle ich mir noch etwas schwierig vor.
Man müsste einen String bereits in der richtigen Größe anlegen und dann
sozusagen überschreiben?

Ja, SO habe ich mir das gewünscht.
DANKE!

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Marshal Bytearray zu String 
Autor: Manfred X
Datum: 15.04.22 21:26

Private Declare Function SysAllocStringByteLen Lib "oleaut32" 
       (ByVal Ptr As Integer, ByVal Length As Integer) As IntPtr
 
Private Declare Function SysFreeString Lib "oleaut32.dll" 
       (ByVal bstr As IntPtr) As UInt32
 
 
 
Private Function BytearrayToString(ByVal byt() As Byte) As String
 
     Dim str As String, pBstr As IntPtr
 
     Try
         pBstr = SysAllocStringByteLen(Nothing, byt.Length)
         Marshal.Copy(byt, 0, pBstr, byt.Length)
         str = Marshal.PtrToStringBSTR(pBstr)
     Finally
         SysFreeString(pBstr)
     End Try
 
     Return str
 
End Function
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 17.04.22 22:45

Hi,

ich hab' endlich zeit gehabt, das zu testen und es FUNKTIONIERT SUPER!
Die Performance ist unschlagbar gut: 200.000.000 Bytes in unter einer Sekunde!

Ich werde zwar niemals auch nur in die Nähe kommen, aber gibt es ein Größenlimit?
Die 200 MB klappen, 400 gibt ein Out of Memory.
Hauptspeicher hab' ich 32GB und noch viel Luft darin. Erwartet hätte ich 2^31 als Limit.
Und was ich besonders verwirrend finde:
Rufe ich die Routine mehrfach auf, kommt nach ein paar Aufrufen ebenso ein Out of Memory bzw.
ein Pointer mit "0" zurück. Ein Pointer "null" sagt "kein Speicher allokierbar".
(Macht "0" und "null" in der Api einen Unterschied? Die Rückgabewerte sind ja nicht "nullable")

Es kommt mir fast so vor als würde "SysFreeString" den Speicher nicht freigeben.
Mir fällt gerade ein ich könnte dahinter mal ein GC.Collect aufrufen?
Aber unmanaged sollte das doch nichts nützen? Oder?

Ich habe probehalber den
"SysAllocStringByteLen(Nothing, byt.Length)"
durch
"str As New String(" "c, CInt(byt.Length / 2))"
ersetzt und das Handle des Strings ausgelesen und übergeben.
Hat (mit minimalem Performanceverlust) prima funktioniert, aber wieder nur bis ca. 200 MB.

Irgendwo wurde auch "FreeHGlobal" statt "SysFreeString" empfohlen,
das gab unabhängig von der Größe nur Totalabstürze.

Das ist jetzt wirklich nur noch eine Neugier-Frage, denn ich werde nie so große Datenmengen benötigen.
Aber egal, es ist genau die Antwort die ich mir 2000 Posts vorher gewünscht habe.
Danke!

Bye,

Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Manfred X
Datum: 18.04.22 00:15

Hallo!

Ich hatte frühzeitig darauf hingewiesen, dass man eine korrespondierende Bytefolge
komprimieren sollte, statt des Inhalts der Stringvariable.
Du postest im Forum für Fortgeschrittene. Hier wird erwartet, dass man grundlegende
Sachverhalte, wie z.B. Marshalling, selbständig der Dokumentation entnehmen kann.

Verbreite keine Gerüchte,
Ich habe die oben angegebenen Routinen unter Net/Core 6.0 getestet.
Es gibt keine Probleme mit der Freigabe des Speichers (10000 Aufrufe)
und es lassen sich auch extrem lange Stringvariable (Millionen Zeichen)
blitzschnell kopieren (getestet bis 1 GB).

Wenn Du Speicherprobleme hast, wird deren Ursache kaum bei diesen Routinen
liegen. Nähere Angaben möglich?
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Binärdaten als String komprimieren 
Autor: Dilbert
Datum: 18.04.22 01:49

Hi.

Gerüchte? Was für Gerüchte?
Und welche Sachverhalte beim Marshaling soll ich der Doku entnehmen?
Hätte ich diese Frage im Einsteigerforum posten sollen?
Ich kann dir da nicht folgen.
Welche näheren Angaben möchtest du noch?

Maybe hilft dir das:
Ich muss für dieses Projekt Framework 4.8 verwenden, vielleicht gibt es da Unterschiede.
Bei mir passiert das auf 3 PCs:
ein Laptop mit AMD Ryzen, 16GB Win10,
ein Intel I7 16GB Win 7
und ein Ryzen 9 32 GB Win 10.

Bei mir ist noch 3 Tage "Ostern", aber wenn ihr wollt poste ich in ein paar Tagen nochmal den Code der zu den beschriebenen Problemen führt. Wäre interesant ob das Problem an meinen PCs liegt oder ob das bei euch auch passiert.

Wenn ich so drüber nachdenke, ich habe das Programm noch nicht "Stand alone" getestet, immer nur mit "debugger.attached" als Debug-Version. Das werde ich bei Gelegenheit nochmal probieren.

BTW: Schöne Ostern an alle!

Bye, Dilbert

--
while (!asleep()) sheep++;

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Sie sind nicht angemeldet!
Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.

Einloggen  |  Neu registrieren

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel