Модераторы: gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Чтение из БД двоичные данные, Рисунок из базы не хочет лезть обратно 
V
    Опции темы
Doss
Дата 12.10.2011, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 171
Регистрация: 5.10.2007

Репутация: нет
Всего: нет



Доброго всем и здравия!
Знаю, знаю знаю, темы вот они, однако решения в них к сожалению  я не нашел.
Смотрел все темы на эту тематику:
как считать дв.данные и т.д. сохранение картинки.

В общем не могу я считать рисунок из базы.
1. БД-Access 2011
2. Поле-im
3. Поле объекта OLE

Записываю так: Все ОК
Код

using (OleDbConnection conn = new OleDbConnection(connect))
            {
                //-----------------
                try
                {
                    System.IO.Stream btmp2bin = new System.IO.FileStream(@"E:\C#\ImegInsert\БД\fullCA7JAICG.jpg", System.IO.FileMode.Open);
                    System.IO.BinaryReader bin = new System.IO.BinaryReader(btmp2bin);
                    byte[] binfin = bin.ReadBytes((int)bin.BaseStream.Length);

                    conn.Open();
                    //----------------------------------
                    da = new OleDbDataAdapter("INSERT into Imeg(im) Values('" + binfin + "')", conn);
                    DataSet ds = new DataSet();
                    da.Fill(ds, "Imeg");
                    try
                    {
                        ds.AcceptChanges();
                    }
                    catch (SqlException ex)
                    {
                        MessageBox.Show(ex.Message, ex.Source);
                        conn.Close();
                    }
                    btmp2bin.Dispose();
                }
                catch (SqlException ex)
                {
                    MessageBox.Show(ex.Message, ex.Source);
                    conn.Close();
                }
            }
 

Данные записываются отлично, в базе присутствует надпись "Двоичные данные".

А вот мои попытки прочитать этот рисунок и загрузить в pictureBox:

Код

 using (OleDbConnection conn = new OleDbConnection(connect))
            {
                //-----------------
                try
                {
                    conn.Open();
                    //----------------------------------
                    //Первая попытка
                    da = new OleDbDataAdapter("select im from Imeg", conn);
                    DataSet ds = new DataSet();
                    da.Fill(ds, "Imeg");
                    //byte[] myimage = (byte[])ds.Tables["Imeg"].Rows[0].ItemArray.GetValue(0);
                    //MemoryStream mem = new MemoryStream(myimage);
                    //System.Drawing.Image image = System.Drawing.Image.FromStream(mem);// Ошибкак тут!!!!!
                    //pictureBox1.Image = image;

                    //=====================================================================
                    //Вторая попытка!!!
                    OleDbCommand command = new OleDbCommand("select  im from Imeg", conn);
                    OleDbDataReader datareader = command.ExecuteReader();
                    datareader.Read();
                    int bLength = (int)datareader.GetBytes(0, 0, null, 0, int.MaxValue);
                    byte[] myimage = new byte[bLength];
                    datareader.GetBytes(0, 0, myimage, 0, bLength);
                    MessageBox.Show(bLength.ToString());// выдает длину 26
                    MemoryStream mem = new MemoryStream(myimage);
                    Bitmap bmp = new Bitmap(mem);// Как и у всех ошибка тут!!!!!!!!
                    pictureBox1.Image = (Image)bmp;
                    //pictureBox1.Image = new Bitmap(new MemoryStream((byte[])ds.Tables["Imeg"].Rows[0]["im"]));
                    conn.Close();
                    mem.Dispose();
                }
                catch (SqlException ex)
                {
                    MessageBox.Show(ex.Message, ex.Source);
                    conn.Close();
                }
            }

 Помогите пожалуйста с этим вопросом, думаю готовое решение уже пора оставить на сайте. Всем спасибо!!!! smile 

Ошибка Parameter is not valid.

Это сообщение отредактировал(а) Doss - 12.10.2011, 18:30
PM MAIL   Вверх
jonie
Дата 12.10.2011, 19:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 8
Всего: 118



Код

Public Sub WritePicture(KeyID as Integer, DBConn As OleDb.OleDbConnection)
'Get Picture from File or whereever into a byte array
     Dim fs As FileStream = New System.IO.FileStream(fname,
IO.FileMode.Open, IO.FileAccess.Read)
      Dim byt(CInt(fs.Length() - 1)) as Byte
      fs.Read(byt, 0, byt.Length)
      fs.Close()
'Write Picture to database
      Try
               DBConn.Open
               Dim DBCmd as New OleDb.OleDbCommand("UPDATE ALBUMS SET
FrontCoverPicture WHERE KeyID = " & Keyid.ToString, DBConn)
                Dim P As New OleDb.OleDbParameter("@FrontCoverPicture",
OleDb.OleDbType.LongVarBinary, Byt.Length, ParameterDirection.Input, False,
0, 0, Nothing, DataRowVersion.Current, Byt)
                DBCmd.Parameters.Add(P)
                DBCmd.ExecuteNonQuery()
            Catch ex As Exception
               'Display Error Message
            Finally
              DBConn.Close
            End Try
        End If
 End Sub
'Read Image from DataBase 
   Public Function GetPicture(KeyId as integer, DBConn as 
 OleDb.OleDbConnection ) As Image 
            Dim Byt as Byte() 
            Try 
                 DBConn.Open 
                 dim DBCmd as New OleDb.OleDbCommand("SELECT * FROM Albums 
 WHERE KeyId = " & Keyid.ToString, DBConn) 
                 Dim rdr As OleDb.OleDbDataReader = DBCmd.ExecuteReader 
                 While rdr.Read 
                    'Note FrontCoverPicture is the table name of the picture 
 column 
                    If Not rdr("FrontCoverPicture") Is DBNull.Value Then byt 
 = CType(rdr("FrontCoverPicture"), Byte()) 
                    End While 
             Catch ex As Exception 
                'Display Error Message 
                 Return Nothing 
             Finally 
                 DBConn.Close 
             End Try 
         End If 
         Return Image.FromStream(New IO.MemoryStream(byt)) 
     End Function

© http://www.eggheadcafe.com/community/aspne...net-coding.aspx


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Doss
Дата 12.10.2011, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 171
Регистрация: 5.10.2007

Репутация: нет
Всего: нет



jonie, все верно, однако в чем моя ошибка, не могу я из двоичного вида в Bitmap залить. Кстати, VB.Net можно представить в C#. Смотрел я 
ссылку. Не вижу отличия принципиального. Где же тут чудесное преобразование?

PM MAIL   Вверх
Doss
  Дата 13.10.2011, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 171
Регистрация: 5.10.2007

Репутация: нет
Всего: нет



Никто не поделиться ...?
PM MAIL   Вверх
Doss
Дата 14.10.2011, 10:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 171
Регистрация: 5.10.2007

Репутация: нет
Всего: нет



Проблема еще не решена.
Насколько я понял и проверил, запись в базу либо не правильна, либо данные, записанные так и должны представляться.
Вот здесь:
Код

 System.IO.Stream btmp2bin = new System.IO.FileStream(@"E:\C#\ImegInsert\БД\fullCA7JAICG.jpg", System.IO.FileMode.Open);
                    System.IO.BinaryReader bin = new System.IO.BinaryReader(btmp2bin);
                    byte[] binfin = bin.ReadBytes((int)bin.BaseStream.Length);
// Проверил размер binfin и получил: 17350
                    conn.Open();
                    //----------------------------------
                    da = new OleDbDataAdapter("INSERT into Imeg(im) Values('" + binfin + "')", conn);


А проверив тут:
Код

 OleDbCommand command = new OleDbCommand("select  im from Imeg", conn);
                    OleDbDataReader datareader = command.ExecuteReader();
                    datareader.Read();
                    int bLength = (int)datareader.GetBytes(0, 0, null, 0, int.MaxValue);
//Получил размер 26

Что то не логично.
К примеру если я копирую (ctrl+c) и вставляю в поле базы, оно отображается как "Поле".
При всех тех же "фокусах" получаю размер 17801
Опять же одни и тот же рисунок, разные размеры!!! Я не могу понять ПОЧЕМУ?
//=====
Ну допустим запись правильна.
Тогда как мне эти двоичные данные считать из этого поля базы и воткнуть в поток??? smile 
Тогда как далее я этот поток передаю в конструктор MemoryStream() и
далее к примеру так 
Код

 MemoryStream stream = new MemoryStream(bytes);
                return Image.FromStream(stream);

либо так 
Код

/pictureBox1.Image = Image. FromStream(new MemoryStream(buf));

Примеров много однако, но как я понял, они ориентированы на хранение ссылок в БД, а рисунки на диске.
Прошу помочь разобраться в этом вопросе.
1.Опять же одни и тот же рисунок, разные размеры!!! Я не могу понять ПОЧЕМУ?
2.Тогда как мне эти двоичные данные считать из этого поля базы и воткнуть в поток???

Справочно:
Имею  методы из форума:
Код

 public static byte[] GetPhoto(string filePath)
        {
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            byte[] photo = br.ReadBytes((int)fs.Length);
            br.Close();
            fs.Close();
            return photo;
        }
 public Image ImageFromBytes(byte[] bytes)
        {
            try
            {
                MemoryStream stream = new MemoryStream(bytes);
                return Image.FromStream(stream);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, ex.Source);
                
            }
            return null;
        }
        //=============================================
        public Bitmap BitmapFromBytes(byte[] bytes)
        {
            try
            {
                MemoryStream stream = new MemoryStream(bytes);
                return (Bitmap)Image.FromStream(stream);
            }
            catch (Exception ex) { MessageBox.Show(ex.Message, ex.Source); }
            return null;
        }
        //==============================================
        public byte[] BitmapToBytes(Bitmap bitmap)
        {
            try
            {
                MemoryStream stream = new MemoryStream();
                bitmap.Save(stream, ImageFormat.Png);
                stream.Position = 0;
                BinaryReader reader = new BinaryReader(stream);
                return reader.ReadBytes((int)stream.Length);
            }
            catch (Exception ex) { MessageBox.Show(ex.Message, ex.Source); }
            return null;
        }

PM MAIL   Вверх
Doss
Дата 15.10.2011, 07:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 171
Регистрация: 5.10.2007

Репутация: нет
Всего: нет



Всем большое спасибо за участие, ведь форум предназначен именно для молчаливого вербального понимание неправда ли? smile 

Вопрос РЕШЕН!!!!! smile 

Для завершения данной темы опишу все суть и код:

В общем большой двоичный объект (BLOB) можно записывать в базу данных в виде двоичных или символьных данных в зависимости от типа поля источника данных. BLOB — это общий термин для типов данных text, ntext и image, используемых, как правило, для хранения документов и изображений.

Чтобы записать значение BLOB в базу данных, выполняется соответствующая инструкция INSERT или UPDATE, передав значение BLOB в качестве входного параметра. Если объект BLOB хранится как текст, например поле SQL Server text, можно передать значение BLOB в виде строкового параметра. Если объект BLOB хранится в двоичном формате, например поле SQL Server image, в качестве двоичного параметра можно передать массив с типом данных byte.
Что мы и делаем ниже:
Код

 string photoFilePath = @"E:\C#\ImegInsert\БД\fullCA7JAICG1.jpg";
            AddEmployee(photoFilePath);
//Вызываем метод который описан ниже
 public static void AddEmployee(string photoFilePath)
        {
            byte[] photo = GetPhoto(photoFilePath);
            using (OleDbConnection connection = new OleDbConnection(connect))
            {
                OleDbCommand command = new OleDbCommand(
                "INSERT into Imeg(im,Pid) Values(@im,@Pid)", connection);
                command.Parameters.Add("@im", OleDbType .LongVarBinary, photo.Length).Value = photo;
                command.Parameters.Add("@Pid", OleDbType.VarChar).Value = "Привет";
                connection.Open();
                command.ExecuteNonQuery();
            }
        }
//Метод GetPhoto() ниже
 public static byte[] GetPhoto(string filePath)
        {
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            byte[] photo = br.ReadBytes((int)fs.Length);
            br.Close();
            fs.Close();
            return photo;
        }


Ну понятно, что в базе два поля кроме счетчика это im (BLOB) и Pid (Text)
Поехали далее, вот теперь записанные данные в базе необходимо прочитать, а желательно фото или рисунок отобразить в чем-либо, ну к примеру в  pictureBox.
По умолчанию объект DataReader загружает входящие данные в виде строки, как только вся строка данных будет в наличии. Однако для больших двоичных объектов (BLOB) требуется другая процедура, поскольку они могут содержать гигабайты данных, которые невозможно уместить в одной строке. Метод Command.ExecuteReader имеет перегрузку, которая принимает аргумент CommandBehavior, чтобы изменять характер действий объекта DataReader по умолчанию. Аргумент SequentialAccess можно передать методу ExecuteReader, чтобы изменить характер действий объекта DataReader по умолчанию, чтобы он загружал не строки данных, а последовательно сами данные по мере их поступления. Это идеально подходит для загрузки больших двоичных объектов или других больших структур данных. Отметим, что этот характер действий может зависеть от источника данных. Например, при возвращении большого двоичного объекта из Microsoft Access он загружается в память целиком, а не последовательно по мере поступления.

При указании объекту DataReader использовать метод SequentialAccess важно отметить последовательность, в которой должны открываться возвращенные поля. При характере действий объекта DataReader по умолчанию, когда загружается вся строка целиком, как только она есть в наличии, пока не будет считана следующая строка, доступ к возвращенным полям можно получить в любом порядке. Однако при использовании метода SequentialAccess открывать поля, возвращенные объектом DataReader, необходимо по порядку. Например, если запрос возвращает три столбца и третий из них — это большой двоичный объект, необходимо возвратить значение первого и второго поля перед тем, как открыть данные большого двоичного объекта в третьем поле. Если открыть третье поле сначала, то значения первого и второго полей будут недоступны. Происходит это потому, что метод SequentialAccess внес изменение в объект DataReader, согласно которому данные должны возвращаться последовательно. Поэтому, если объект DataReader считал последующие данные раньше предыдущих, предыдущие данные будут недоступны.

При доступе к данным в поле большого двоичного объекта используйте типизированные методы доступа GetBytes или GetChars объекта DataReader, которые заполняют массив данными. Также можно использовать метод GetString для символьных данных, однако для сохранения ресурсов системы лучше не загружать все значение большого двоичного объекта в одну строковую переменную. Вместо этого можно указать определенный размер буфера данных, которые должны быть возвращены, а также начальное положение для первого байта или символа, читаемого из возвращенных данных. Методы GetBytes и GetChars возвращают значение long, которое представляет число возвращенных байт или символов. Если методу GetBytes или GetChars передать пустой массив, то возвращенное длинное значение будет общим числом байт или символов в большом двоичном объекте. При необходимости можно в массиве указать индекс в качестве начальной позиции для читаемых данных.
Вот и начали:
Код

using (OleDbConnection conn = new OleDbConnection(connect))
            {
                //-----------------
                try
                {
                    conn.Open();
                    //----------------------------------
                    OleDbCommand command = new OleDbCommand(
                       "SELECT Pid, im FROM Imeg where id=14", conn);
                    FileStream stream;
                    BinaryWriter writer;
                    int bufferSize = 20000;
                    byte[] outByte = new byte[bufferSize];
                    long retval;
                    long startIndex = 0;
                    string pubID = "";
                    OleDbDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess);
                    while (reader.Read())
                    {
                        pubID = reader.GetString(0);
                        stream = new FileStream(pubID , FileMode.OpenOrCreate, FileAccess.Write);
                        writer = new BinaryWriter(stream);
                        startIndex = 0;
                        retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);
                        while (retval == bufferSize)
                        {
                            writer.Write(outByte);
                            writer.Flush();
                            startIndex += bufferSize;
                            retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);
                        }
                        writer.Write(outByte, 0, (int)retval - 1);
                        writer.Flush();
                        writer.Close();
                        stream.Close();
                    }
                    reader.Close();
// Отобразим его в pictureBox
                    pictureBox1.Image = ImageFromBytes(outByte);
                    conn.Close();

                }
                catch (SqlException ex)
                {
                    MessageBox.Show(ex.Message, ex.Source);
                    conn.Close();
                }
            }

//Метод  ImageFromBytes вот он
 public Image ImageFromBytes(byte[] bytes)
        {
            try
            {
                MemoryStream stream = new MemoryStream(bytes);
                return Image.FromStream(stream);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, ex.Source);

            }
            return null;
        }


Надеюсь помогу следующим форумчанам, у кого возникнут такие же вопросы.
 smile 
Кстати, рисунок следующий
user posted image

Это сообщение отредактировал(а) Doss - 15.10.2011, 07:44
PM MAIL   Вверх
Doss
Дата 17.11.2011, 19:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 171
Регистрация: 5.10.2007

Репутация: нет
Всего: нет



Лучше BMW - только новое BMW!!!!-)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
stab
mr.DUDA
Exception

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, stab, mr.DUDA, Exception.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Базы данных под .NET | Следующая тема »


 




[ Время генерации скрипта: 0.0673 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.