Laden...

SQLite: Object in Byte[] konvertieren

Erstellt von Andybritten vor 14 Jahren Letzter Beitrag vor 14 Jahren 6.112 Views
A
Andybritten Themenstarter:in
92 Beiträge seit 2009
vor 14 Jahren
SQLite: Object in Byte[] konvertieren

Hey!

Ich hab ein kleines Problem.
Ich möchte aus einem ausgelesenen Wert ein Byte Array machen.
Jedoch kann ich es vorher nicht in einen String umwandeln weil dann nur sinnloses Zeugs rauskommt.
Also muss ich es schaffen irgendwie den Wert direkt in ein Byte Array zu bauen.

Mein Code sieht wie folgt aus:

 
.....               
byte[] bbyte = (byte[]) Zeile["name_value"];
Result += Rename(bbyte);
.......

Das war meine Idee es umzusetzen jedoch bekomme ich den folgenden Error:

Das Objekt des Typs "System.String" kann nicht in Typ "System.Byte[]" umgewandelt werden.

Da werde ich leider nicht schlau draus....

Hat jemand eine Idee wie man diesen Wert direkt in ein ByteArray umsetzen kann?
Wäre echt dankbar!

Liebe Grüße

S
72 Beiträge seit 2009
vor 14 Jahren

Hallo Andybritten,

mir fällt gerade nur MSDN - BitConverter ein.

A
Andybritten Themenstarter:in
92 Beiträge seit 2009
vor 14 Jahren

Hey!

Danke für die Antwort aber das klappt leider nicht 😦

1-Argument: kann nicht von "object" in "bool" konvertiert werden.

Noch wer anders eine Idee?

S
72 Beiträge seit 2009
vor 14 Jahren

Hallo Andybritten,

was versuchst du da überhaupt?
Das sieht mir irgendwie nach wilder umcasterei von Objekten aus.
Von wo nach wo soll es überhaupt gehen?

Zusätzlich würde ich dich gerne auf Punkt 5 der Regeln hinweisen. [Hinweis] Wie poste ich richtig?

3.170 Beiträge seit 2006
vor 14 Jahren

Hallo,

Da werde ich leider nicht schlau draus....

Das geht mir mit Deiner ersten Frage ehrlich gesagt genauso:

Du sagst, Du kannst den Wert nicht in einen String umwandeln.
In dem von Dir geposteten Lösungsansatz wird der Wert ja aus Zeile["name_value"] gelesen.
Der ebenfalls geposteten Fehlermeldung zufolge handelt es sich dabei aber bereits um einen String,

Dein Ansatz - würde er funktionieren - käme also nach meinem Verständnis schon zu spät.

Du wirst schon mal erklären müssen, um was für einen ominösen Wert es sich da dreht.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

A
Andybritten Themenstarter:in
92 Beiträge seit 2009
vor 14 Jahren

Also.
Es handelt sich um eine SQLite Datenbankdatei die ich auselsen möchte.
Die SQLite Class sieht wie folgt aus: (Diese ist nicht von mir)

    #region SQLite
    public class SQLiteBase
    {
        // imports system functions for work with pointers
        [DllImport("kernel32")]
        private extern static IntPtr HeapAlloc(IntPtr heap, UInt32 flags, UInt32 bytes);

        [DllImport("kernel32")]
        private extern static IntPtr GetProcessHeap();

        [DllImport("kernel32")]
        private extern static int lstrlen(IntPtr str);

        // imports SQLite functions
        [DllImport("sqlite3")]
        private static extern int sqlite3_open(IntPtr fileName, out IntPtr database);

        [DllImport("sqlite3")]
        private static extern int sqlite3_close(IntPtr database);

        [DllImport("sqlite3")]
        private static extern int sqlite3_exec(IntPtr database, IntPtr query, IntPtr callback, IntPtr arguments, out IntPtr error);

        [DllImport("sqlite3")]
        private static extern IntPtr sqlite3_errmsg(IntPtr database);

        [DllImport("sqlite3")]
        private static extern int sqlite3_prepare_v2(IntPtr database, IntPtr query, int length, out IntPtr statement, out IntPtr tail);

        [DllImport("sqlite3")]
        private static extern int sqlite3_step(IntPtr statement);

        [DllImport("sqlite3")]
        private static extern int sqlite3_column_count(IntPtr statement);

        [DllImport("sqlite3")]
        private static extern IntPtr sqlite3_column_name(IntPtr statement, int columnNumber);

        [DllImport("sqlite3")]
        private static extern int sqlite3_column_type(IntPtr statement, int columnNumber);

        [DllImport("sqlite3")]
        private static extern int sqlite3_column_int(IntPtr statement, int columnNumber);

        [DllImport("sqlite3")]
        private static extern double sqlite3_column_double(IntPtr statement, int columnNumber);

        [DllImport("sqlite3")]
        private static extern IntPtr sqlite3_column_text(IntPtr statement, int columnNumber);

        [DllImport("sqlite3")]
        private static extern IntPtr sqlite3_column_blob(IntPtr statement, int columnNumber);

        [DllImport("sqlite3")]
        private static extern IntPtr sqlite3_column_table_name(IntPtr statement, int columnNumber);

        [DllImport("sqlite3")]
        private static extern int sqlite3_finalize(IntPtr handle);

        // SQLite constants
        private const int SQL_OK = 0;
        private const int SQL_ROW = 100;
        private const int SQL_DONE = 101;

        /// <summary>
        /// SQLite data types.
        /// </summary>
        public enum SQLiteDataTypes
        {
            /// <summary>
            /// Integer numbers.
            /// </summary>
            INT = 1,
            /// <summary>
            /// Decimal numbers.
            /// </summary>
            FLOAT,
            /// <summary>
            /// All kinds of texts.
            /// </summary>
            TEXT,
            /// <summary>
            /// Blob objects - binary large objects.
            /// </summary>
            BLOB,
            /// <summary>
            /// Nothing.
            /// </summary>
            NULL
        };

        // pointer to database
        private IntPtr database;

        /// <summary>
        /// Creates new instance of SQLiteBase class with no database attached.
        /// </summary>
        public SQLiteBase()
        {
            database = IntPtr.Zero;
        }

        /// <summary>
        /// Creates new instance of SQLiteBase class and opens database with given name.
        /// </summary>
        /// <param name="baseName">Name (and path) to SQLite database file</param>
        public SQLiteBase(String baseName)
        {
            OpenDatabase(baseName);
        }

        /// <summary>
        /// Opens database.
        /// </summary>
        /// <param name="baseName">Name of database file</param>
        public void OpenDatabase(String baseName)
        {
            // opens database
            if (sqlite3_open(StringToPointer(baseName), out database) != SQL_OK)
            {
                // if there is some error, database pointer is set to 0 and exception is throws
                database = IntPtr.Zero;
                throw new Exception("Error with opening database " + baseName + "!");
            }
        }

        /// <summary>
        /// Closes opened database.
        /// </summary>
        public void CloseDatabase()
        {
            // closes the database if there is one opened
            if (database != IntPtr.Zero)
            {
                sqlite3_close(database);
            }
        }

        /// <summary>
        /// Returns the list of tables in opened database.
        /// </summary>
        /// <returns></returns>
        public ArrayList GetTables()
        {
            // executes query that select names of all tables and views in master table of every database
            String query = "SELECT name FROM sqlite_master " +
                                        "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'" +
                                        "UNION ALL " +
                                        "SELECT name FROM sqlite_temp_master " +
                                        "WHERE type IN ('table','view') " +
                                        "ORDER BY 1";
            DataTable table = ExecuteQuery(query);

            // when table is generater, it writes all table names in list that is returned
            ArrayList list = new ArrayList();
            foreach (DataRow row in table.Rows)
            {
                list.Add(row.ItemArray[0].ToString());
            }
            return list;
        }

        /// <summary>
        /// Executes query that does not return anything (e.g. UPDATE, INSERT, DELETE).
        /// </summary>
        /// <param name="query"></param>
        public void ExecuteNonQuery(String query)
        {
            // calles SQLite function that executes non-query
            IntPtr error;
            sqlite3_exec(database, StringToPointer(query), IntPtr.Zero, IntPtr.Zero, out error);
            // if there is error, excetion is thrown
            if (error != IntPtr.Zero)
                throw new Exception("Error with executing non-query: \"" + query + "\"!\n" + PointerToString(sqlite3_errmsg(error)));
        }

        /// <summary>
        /// Executes query that does return something (e.g. SELECT).
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public DataTable ExecuteQuery(String query)
        {
            // processed query
            IntPtr statement;

            // excess data, it has no use
            IntPtr excessData;

            // process query and make statement
            sqlite3_prepare_v2(database, StringToPointer(query), GetPointerLenght(StringToPointer(query)), out statement, out excessData);

            // table for result of function
            DataTable table = new DataTable();

            // reads first row - it is different from next rows because it also creates table columns
            // result - returns SLQ_ROW while there is next row
            int result = ReadFirstRow(statement, ref table);

            // reads rows
            while (result == SQL_ROW)
            {
                result = ReadNextRow(statement, ref table);
            }

            // finalize executing this query
            sqlite3_finalize(statement);

            // returns table
            return table;
        }

        // private function for reading firs row and creating DataTable
        private int ReadFirstRow(IntPtr statement, ref DataTable table)
        {
            // create new instance of DataTable with name "resultTable"
            table = new DataTable("resultTable");

            // evaluates statement
            int resultType = sqlite3_step(statement);

            // if result of statement is SQL_ROW, create new table and write row in it
            if (resultType == SQL_ROW)
            {
                // returns number of columns returned by statement
                int columnCount = sqlite3_column_count(statement);

                // declartaion of variables for reading first row
                String columnName = "";
                int columnType = 0;
                object[] columnValues = new object[columnCount];

                // reads columns one by one
                for (int i = 0; i < columnCount; i++)
                {
                    // returns the name of current column
                    columnName = PointerToString(sqlite3_column_name(statement, i));

                    // returns the type of current column
                    columnType = sqlite3_column_type(statement, i);

                    // checks type of columns - neccessary because different functions are required for different types
                    switch (columnType)
                    {
                        // in case of integer column
                        case (int)SQLiteDataTypes.INT:
                            {
                                // adds new integer column to table
                                table.Columns.Add(columnName, Type.GetType("System.Int32"));

                                // writes column value in object array
                                columnValues[i] = sqlite3_column_int(statement, i);
                                break;
                            }
                        // same as for integer, this one is for float
                        case (int)SQLiteDataTypes.FLOAT:
                            {
                                table.Columns.Add(columnName, Type.GetType("System.Single"));
                                columnValues[i] = sqlite3_column_double(statement, i);
                                break;
                            }
                        // ... for text
                        case (int)SQLiteDataTypes.TEXT:
                            {
                                table.Columns.Add(columnName, Type.GetType("System.String"));
                                columnValues[i] = PointerToString(sqlite3_column_text(statement, i));
                                break;
                            }
                        // ... for blob - blob are written in table as strings!!
                        case (int)SQLiteDataTypes.BLOB:
                            {
                                table.Columns.Add(columnName, Type.GetType("System.String"));
                                columnValues[i] = PointerToString(sqlite3_column_blob(statement, i));
                                break;
                            }
                        // in case of something other, value is read as string
                        default:
                            {
                                table.Columns.Add(columnName, Type.GetType("System.String"));
                                columnValues[i] = "";
                                break;
                            }
                    }
                }

                // writes column values to table
                table.Rows.Add(columnValues);
            }

            // evalute statemnet for next results
            return sqlite3_step(statement);
        }

        // private function for reading rows other than first
        // it' same like first row, only without creating table and columns
        private int ReadNextRow(IntPtr statement, ref DataTable table)
        {
            int columnCount = sqlite3_column_count(statement);

            int columnType = 0;
            object[] columnValues = new object[columnCount];

            for (int i = 0; i < columnCount; i++)
            {
                columnType = sqlite3_column_type(statement, i);

                switch (columnType)
                {
                    case (int)SQLiteDataTypes.INT:
                        {
                            columnValues[i] = sqlite3_column_int(statement, i);
                            break;
                        }
                    case (int)SQLiteDataTypes.FLOAT:
                        {
                            columnValues[i] = sqlite3_column_double(statement, i);
                            break;
                        }
                    case (int)SQLiteDataTypes.TEXT:
                        {
                            columnValues[i] = PointerToString(sqlite3_column_text(statement, i));
                            break;
                        }
                    case (int)SQLiteDataTypes.BLOB:
                        {
                            columnValues[i] = PointerToString(sqlite3_column_blob(statement, i));
                            break;
                        }
                    default:
                        {
                            columnValues[i] = "";
                            break;
                        }
                }
            }
            table.Rows.Add(columnValues);
            return sqlite3_step(statement);
        }

        // converts string to pointer
        private IntPtr StringToPointer(String str)
        {
            // if string is null, pointer is 0
            if (str == null)
            {
                return IntPtr.Zero;
            }
            else
            {
                // else, convert it to pointer
                Encoding encoding = Encoding.UTF8;
                Byte[] bytes = encoding.GetBytes(str);
                int length = bytes.Length + 1;
                IntPtr pointer = HeapAlloc(GetProcessHeap(), 0, (UInt32)length);
                Marshal.Copy(bytes, 0, pointer, bytes.Length);
                Marshal.WriteByte(pointer, bytes.Length, 0);
                return pointer;
            }
        }

        // convert pointer to string
        private String PointerToString(IntPtr ptr)
        {
            if (ptr == IntPtr.Zero)
                return null;

            Encoding encoding = Encoding.UTF8;

            int length = GetPointerLenght(ptr);
            Byte[] bytes = new Byte[length];
            Marshal.Copy(ptr, bytes, 0, length);
            return encoding.GetString(bytes, 0, length);
        }

        // returns length of pointer
        private int GetPointerLenght(IntPtr ptr)
        {
            if (ptr == IntPtr.Zero)
                return 0;
            return lstrlen(ptr);
        }
    }
    #endregion

Und mein Code sieht wie folgt aus:

SQLiteBase db = new SQLiteBase(Environment.GetFolderPath(PfadZurDatenbankDatei);
            DataTable table = db.ExecuteQuery("SELECT * FROM database;");

            foreach (DataRow Zeile in table.Rows)
            {
                string Result = Decrypt(Zeile["name_value"]);

                Console.WriteLine(Result);
            }

Die Decryption Routine benötigt ein Byte Array als input.
Und Zeile["name_value"] ist noch kein String man kann es aber mit: Zeile["name_value"].ToString() zu einem String machen.
Jedoch wenn ich diesen String dann in ein ByteArray umwandel stimmen die Werte nicht mehr.
Deswegen muss ich einen Weg finden den Ausgelesenen Wert DIREKT in ein byte Array umzuwandeln.

Ich hoffe meine Problembeschreibung war diesmal besser.

3.170 Beiträge seit 2006
vor 14 Jahren

Hallo,

in der switch-case-Abfrage in den ReadLine-Methoden wird alles als String eingelesen, was nicht INT, FLOAT, TEXT, BLOB oder NULL ist. Ich vermute daher, daß Dein _Zeile["name_value"] _ entgegen Deiner Behauptung sehr wohl einen String enthält, und da wohl auch das Problem herrührt.

Ich empfehle diese Dokumentation der SQLite3-Datentypen

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

F
10.010 Beiträge seit 2004
vor 14 Jahren

@Andybritten:
Bitte tu dir das nicht an.

Diese komische SQLite Klasse ist so grausselig und schlecht, das es nicht wirklich
sinnvoll ist.

Es gibt einen guten SQLite ADO.NET Provider der ganz Frameworkkonform
den Zugriff auf SQLite datenbanken erlaubt.
http://sqlite.phxsoftware.com/

Da musst du dann nichts irgendwie selber hin und her Konvertieren.

A
Andybritten Themenstarter:in
92 Beiträge seit 2009
vor 14 Jahren

Hey!

Danke für deine Antwort aber das löst immer noch nicht mein Problem wie ich das "Object" zu einem "Byte Array" konvertiert bekomme...
Und wie bereits gesagt wurde... Wenn ich den Wert.ToString() mache bekomm ich einen Fehler beim decoden....

Grüße

FZelle:
Danke ich werd mir deine Klasse mal anschauen!
Aber erst morgen früh ^^

A
Andybritten Themenstarter:in
92 Beiträge seit 2009
vor 14 Jahren

Allsssoooo nach ein bisschen rumprobieren habe ich es zum Laufen bekommen jedoch bleib ich bei dem selben Problem stecken wie zuvor!
Jedoch verstehe ich wieder etwas nicht....

Also mein Code sieht wie folgt aus:

 
                using (DbConnection cnn = new SQLiteConnection("Data Source=" + datapath))
                using (DbCommand cmd = cnn.CreateCommand())
                {
                    cnn.Open();
                    cmd.CommandText = "SELECT * FROM database";

                    using (DbDataReader reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            string name = Decrypt(reader[5]);

                            Console.WriteLine(name);
                        }
                    }
                }

Jetzt bekomme ich in der Zeile:

                            string name = Decrypt(reader[5]);

Den selben Error wie zuvor:

1-Argument: kann nicht von "object" in "byte[]" konvertiert werden.

Und nun zu dem was ich nicht verstehe.
Ich hab mir mal den Typ ausgeben lassen von dem "reader[5]" Wert.

string typeofthisshit = reader[5].GetType().ToString();

Und ratet mal was als Ergebnis rauskam....

System.Byte[]

Jetzt verstehe ich aber nicht warum er mir dann beim Aufruf der Decryption Methode anzeigt, dass er object nicht zu byte[] konvertieren kann wenns doch eh schon ein bytearray ist....

Und falls noch jemand Zweifel an der Decryption methode hat:

        public static string Decrypt(byte[] Datas)
        {
            ..............................
        }

Ich steh grad total auf dem Schlauch! 😦

3.170 Beiträge seit 2006
vor 14 Jahren

Hallo,

wenn es sich bei dem Wert schon um ein byte[] handelt, kannst Du ihn auch beim übergeben einfach casten.

string name = Decrypt((byte[])reader[5]);

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

A
Andybritten Themenstarter:in
92 Beiträge seit 2009
vor 14 Jahren

Es klappt!!!! Danke Leute.
Bei der alten methode hatte ich es mit (byte[]) probiert nur eben hab ich es vergessen...
Vielen Dank für die Hilfe! 😃