German Liste aus BLOB Feld lesen (SQLite)

Palle

Member
Licensed User
Hallo,

Listen mit Messwerten wurden mit folgendem Code als BLOB in einer SQLite-Datenbank gespeichert, da es sich teilweise je Datensatz um 1000e Werte handelt.

B4X:
    Dim B(RateList.Size) As Byte
    
    For i = 0 To RateList.Size - 1
        B(i) = RateList.Get(i)
    Next
    
    GlobalCodes.TSQL.ExecNonQuery2("INSERT INTO Rates VALUES(NULL, '" & RecordID & "', ?)", Array As Object(B))

Leider klappt das Einlesen nicht, versuche schon seit Stunden eine Lösung zu finden...

B4X:
Cursor1 = GlobalCodes.TSQL.ExecQuery2("SELECT RateList FROM Rates WHERE RecordID = '" & RecordViewID & "'", Array As String("RateList"))
Cursor1.Position = 0

Dim B() As Byte
B = Cursor1.GetBlob("RateList")
        
Dim InputStream1 As InputStream
InputStream1.InitializeFromBytesArray(B, 0, B.Length)

...

Das wird sicherlich nicht funktionieren und ich wäre für einen Lösungsansatz sehr dankbar.

Palle
 

Alexander Stolte

Expert
Licensed User
Longtime User
Ich hab einfach nur "blob" in der suche eingegeben und fand die Lösung innerhalb von 5 Sekunden.
B4X:
Dim Buffer() As Byte 'declare an empty byte array
Buffer = res.GetBlob("RateList")
Dim InputStream1 As InputStream
InputStream1.InitializeFromBytesArray(Buffer, 0, Buffer.Length)
Dim bc As ByteConverter
Dim st As String = bc.StringFromBytes(Buffer, "UTF8")
InputStream1.Close

Und du solltest dringend von Cursor, auf ResultSet umsteigen. Und deine Parameter immer mit den Fragezeichen übermitteln.
 

Palle

Member
Licensed User
Danke für Ihren Kommentar - das hatte ich auch gleich gefunden, aber irgendwie funktioniert es nicht.

B4X:
Cursor1 = GlobalCodes.TSQL.ExecQuery("SELECT RateList FROM Rates WHERE RecordID = '" & RecordViewID & "'")

        Cursor1.Position = 0
        Dim B() As Byte
        B = Cursor1.GetBlob("RateList")

        Dim BC As ByteConverter
        Dim S As String = BC.StringFromBytes(B, "UTF8")

1661195804117.png

Das sind die Daten im String.
 

Palle

Member
Licensed User
Es ist eine Liste mit 1000en Messwerten pro Datensatz und ich will nicht jeden Wert einzeln speichern, daher mein Gedanke die Liste als in ein Blob Feld abzulegen, das geht dann auch schneller als jeden einzelnen Datensatz als TEXT.
Das Speichern der Werte aus einer LIST klappt hervorragend, aber wie bekomme ich diese Werte wieder aus dem BLOB Feld in die LIST ???
 

DonManfred

Expert
Licensed User
Longtime User
Es ist eine Liste mit 1000en Messwerten pro Datensatz und ich will nicht jeden Wert einzeln speichern, daher mein Gedanke die Liste als in ein Blob Feld abzulegen, das geht dann auch schneller als jeden einzelnen Datensatz als TEXT.
Was genau hast Du gespeichert? bzw. wie. Poste mal einen Beispielcode wie du Daten gesammelt und gespeichert hast. Dann verstehen wir vielleicht besser was da drin steht und wie man das wieder "zurück" bekommt.
 

Palle

Member
Licensed User
Im 1. Post steht der Code zu Speichern, die List enthält nur die Messwerte:

88
90
89
86
85
usw.

und irgendwie muss ich die wieder zurück bekommen...
 

Palle

Member
Licensed User
Die Tabelle:

"CREATE TABLE IF NOT EXISTS Rates (RateID INTEGER PRIMARY KEY, RecordID TEXT, RateList BLOB)"

Die RecordID stellt die Verknüpfung zur eigentlichen Aufzeichnung her. Daher auch wichtig "WHERE RecordID= ..."

Wäre echt dankbar, wenn ihr mir helfen könnt.
 

Palle

Member
Licensed User
Wozu ein Beispielprojekt?? Es geht doch nur darum die Daten wieder aus dem Blob lesbar zurück zu bekommen. Wie die Werte gespeichert wurden ist doch aus dem 1. Post ersichtlich.

Aber vielleicht ist das mit dem Blob auch der falsche Weg...

Trotzdem Danke für die Hilfe.
 

PaulMeuris

Active Member
Licensed User
Wozu ein Beispielprojekt?? Es geht doch nur darum die Daten wieder aus dem Blob lesbar zurück zu bekommen. Wie die Werte gespeichert wurden ist doch aus dem 1. Post ersichtlich.

Aber vielleicht ist das mit dem Blob auch der falsche Weg...

Trotzdem Danke für die Hilfe.
Genau, das mit dem Blob ist der falsche Weg!
Die Datei Structur ist nich gut: eine Tabelle für die Rates und eine Tabelle für die RateList.
Benütze einen JOIN in der SQL query.
 

Palle

Member
Licensed User
Habe nun eine Lösung über StringBuilder gefunden, um die Werte schnell und kompakt in der DB zu speichern und auszulesen.

B4X:
        ' SPEICHERN
        
        Dim SB As StringBuilder
        SB.Initialize
        
        For i = 0 To RateList.Size - 1
            SB.Append(RateList.Get(i) & ",")
        Next
        
        Dim BT() As Byte
        Dim BC As ByteConverter
        BT = BC.StringToBytes(SB, "UTF8")
        
        GlobalCodes.TSQL.ExecNonQuery2("INSERT INTO Rates VALUES(NULL, '" & RecordID & "', ?)", Array As Object(BT))
        
        ' LESEN
        
        Dim BT() As Byte
        BT = Cursor1.GetBlob("RateList")
        Dim BC As ByteConverter
        Dim ST As String = BC.StringFromBytes(BT, "UTF8")
            
        Dim Delimiter As String = ","
        Dim sArray() As String = Regex.Split(Delimiter, ST)
            
        RecordViewList.AddAll(sArray)

Entscheidend ist doch immer, dass am Ende alles funktioniert, wie auch immer - es gibt viele Wege :)
 

ilan

Expert
Licensed User
Longtime User
Was du machen kannst ist die Liste zu einem Base64 Text zu konvertieren und als TEXT Objekt in deiner SQL-DB speichern and dann wieder zu einer Liste konvertieren.

B4X:
Public Sub objectToBase64(obj As Object) As String
    Dim ser As B4XSerializator
    Dim su As StringUtils
    Return su.EncodeBase64(ser.ConvertObjectToBytes(obj))
End Sub

Public Sub base64ToObject(base64 As String) As Object
    Dim ser As B4XSerializator
    Dim su As StringUtils
    Dim a() As Byte = su.DecodeBase64(base64)
    If a.Length = 0 Then Return ""
    Return ser.ConvertBytesToObject(a)
End Sub

um zu speichern benutzt du einfach objectToBase64() funktion und gibst die liste als Objekt ein

um wieder zu einer Liste umzuwandeln kannst es so machen:

B4X:
    Dim tags As String = Cursor.GetString("tags")
    Dim tagslist As List
    tagslist.Initialize
    Dim obj As Object = base64ToObject(tags)
     If obj Is List Then
           Dim l As List = obj
           log(l)
     End If

wenn du jedoch es als BLOB speichern moechtest kannst diese Funktionen benutzen:

B4X:
Public Sub objectToByte(obj As Object)As Byte()
    Dim ser As B4XSerializator
    Return ser.ConvertObjectToBytes(obj)
End Sub

Public Sub byteToObject(data() As Byte)As Object
    Dim ser As B4XSerializator
    Return ser.ConvertBytesToObject(data)
End Sub

ich selber benutze die Bae64 Methode und funktioniert einwandfrei!
 

Palle

Member
Licensed User
Das wäre natürlich auch eine Möglichkeit - danke für Deinen Beitrag.
Die Lösung mit StringBuilder funktioniert wunderbar und vor allem schnell auch bei tausenden Messwerten. Das Laden unter Windows (Delphi/FireDAC) geht auch ohne Probleme, so dass die Daten unter Windows geladen und ausgewertet werden können...
 
Top