C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: MDBに画像を保存した後、読み込んでPictureboxに


(過去ログ 92 を表示中)

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■55358 / inTopicNo.1)  MDBに画像を保存した後、読み込んでPictureboxに
  
□投稿者/ ももす (1回)-(2010/11/28(Sun) 07:40:58)

分類:[C#] 

開発環境:VisualStudio2005 
使用言語:C#
使用DB:mdb(Access2003)

お世話になります。
どうしてもわからなくなり、ここに投稿させていただきました。

さっそくですが、やろうとしている事は下記になります。
下記の1については問題なくできますが、どうしても'2.'と'3.'でつまづいており、
'4.'の段階までいけずに困っています。

*****************************************************************
*目的1:
〜保存〜
1.画像を取り込む
2.Button1を押すと、画像をレコードの指定のカラムに書き込む
〜読み込み〜
3.Button2を押すと、レコードの指定のカラムから(2.で保存した)画像を取り込む
4.取り込んだ画像をpicturebox1に表示


*****************************************************************
*別案:
別案として、下記方法を試して実行する事はできましたので、
上記方法でのやり方をお願いします。
〜保存〜
button1を押すと・・・
1.画像を取り込む
2.画像をファイルとして保存
3.保存場所のパスをレコードに書き込む
〜読み込み〜
button2を押すと・・・
4.レコードからファイルパスを取り込む
5.ファイルパスから画像を取り込む
6.取り込んだ画像をpictureboxに表示する


*****************************************************************
*試した事:
下記URLを参考に、画像をシリアライズしてmdbに書き込み、
mdbから読み込んでデシリアライズしてpicturebox1に画像を表示
http://hwm5.gyao.ne.jp/cocoa/csharptips/serialize_binaryfileserialize.htm
〜保存〜
1.画像(bmp)を取り込む
2.Button1を押すと、画像をシリアライズしてbyte配列に格納
3.シリアライズしたbyte配列をSQLのInsert文でTestTableに挿入
4.(確認)mdbをAccessで開き、'TestTable'を開くと'Data'には'ロングバイナリデータ'と書かれているので
 書き込みに成功している?
〜読み込み〜
5.Button2を押すと、TestTableの指定のカラムからデータを取り込む(レコード番号はテスト用のため1)
6.データをデシリアライズする ←ここでエラー
6.取り込んだ画像をpicturebox1に表示


*****************************************************************
エラー内容
'System.Runtime.Serialization.SerializationException' のハンドル
されていない例外が mscorlib.dll で発生しました。

追加情報: 入力ストリームは有効なバイナリ形式ではありません開始コンテンツ (バイト):
 15-1C-38-00-02-00-00-00-16-00-0E-00-14-00-2A-00-FF ...


コードは下記になります。
***************************ここから**********************************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Serialize
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public class SerializeClass
        {
        	//string型をImage型に変更
            public Image ImageMember;
        }
        

		//string型からObject型に変更
        static public byte[] Serialize(Image serializeObject)
     〜 省略 〜
		
		//string型からbyte配列型に変更
        static public object Deserialize(byte[] bytesData, SerializationBinder binder)
            {
            //デシリアライズしたオブジェクト
            object deserializedData;

            //バイト配列のメモリストリームを作成
            using (MemoryStream memoryStream = new MemoryStream(bytesData))
            {
                //シリアライズ/デシリアライズをするBinaryFormatterを作成
                BinaryFormatter binFormatter = new BinaryFormatter();

                //デシリアライズ中に読み込むクラスを制御するバインダをセット
                binFormatter.Binder = binder;

                //メモリストリームからオブジェクトをシリアライズ
                deserializedData = binFormatter.Deserialize(memoryStream); ←ここでエラー

                //メモリストリームを閉じる
                memoryStream.Close();
            }

            //デシリアライズしたオブジェクトを返す
            return deserializedData;
        }
		//保存ボタン
        private void button1_Click(object sender, EventArgs e)
        {
            // 画像のURL
            Image _bmp = Image.FromFile("C:\\testBMP.bmp");

            //シリアライズテスト用オブジェクトを作成
            SerializeClass serialize = new SerializeClass();
            serialize.ImageMember = _bmp;

            //オブジェクトをバイト型配列にシリアライズ
            byte[] bytes = Serialize(serialize);
            
            /*
            //DBにデータ保存
            DataRow drow;
            System.Data.OleDb.OleDbDataAdapter dAdp;
            DataSet dSet = new DataSet("TestTable");
            
            System.Data.OleDb.OleDbConnection cn = new System.Data.OleDb.OleDbConnection();

            cn.ConnectionString ="Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=TestMDB.mdb;";
            cn.Open();
            System.Data.OleDb.OleDbCommand com = new System.Data.OleDb.OleDbCommand(
                "insert into TestTable(Data) values('" + bytes + "')",cn);
            try{
                com.ExecuteNonQuery();
                cn.Close();
                MessageBox.Show("保存成功","通知");
            }
            catch(Exception ex)
            {
                cn.Close();
                MessageBox.Show(ex.Message);
            }
        }

		//読み込み&表示ボタン
        private void button2_Click(object sender, EventArgs e)
        {
            //DBにデータ保存
            System.Data.OleDb.OleDbDataAdapter dAdp;
            DataSet dSet = new DataSet("TestTable");
            System.Data.OleDb.OleDbConnection cn = new System.Data.OleDb.OleDbConnection();
            cn.ConnectionString ="Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=TestMDB.mdb;";
            dAdp = new System.Data.OleDb.OleDbDataAdapter("SELECT TestTable.Data FROM TestTable", cn);
            dAdp.Fill(dSet, "TestTable");
            int c = dSet.Tables["TestTable"].Rows.Count;
            if (c > 0)
            {   
                Byte[] byteBLOBData = new Byte[0];
                byteBLOBData = (Byte[])(dSet.Tables["TestTable"].Rows[c - 1]["Data"]);
                SerializeClass deserialize = Deserialize(byteBLOBData, null) as SerializeClass;
                //MemoryStream stmBLOBData = new MemoryStream(deserialize.ImageMember);

                pictureBox1.Image = deserialize.ImageMember;

            }
            cn.Close();
            
            Byte[] byteImageData = new Byte[0];
            
            byteImageData = (byte[])drow.ItemArray[0];

            //バイト型配列の内容をデシリアライズしてオブジェクトを復元
            SerializeClass deserialize = Deserialize(byteImageData, null) as SerializeClass; ←ここでエラー
            
            pictureBox1.Image = deserialize.ImageMember;
            
        }
    }
}
***************************ここまで**********************************
クラス=SerializeClass、メソッド=Serialize、Deserializeについては下記URLを
参考に引数をstring型から各型に変更したものになります。
http://hwm5.gyao.ne.jp/cocoa/csharptips/serialize_binaryfileserialize.htm

*********************************************************************
テスト用の環境は下記になります。
*テスト用環境
MDBのテーブル構造:
MDBファイル名:TestMDB.mdb
テーブル名:TestTable
フィールド名|データ型
Data  |OLEオブジェクト型

テスト用フォーム内構成
form1
└ picturebox1
└ button1
└ button2

取り込む画像形式:bmp(jpg,gifは尚可)


ファイル容量の増加及びそれによるDBの読込速度の低下、mdbの容量限界など、
後者の別案の方がDBの仕様的に良いのは理解しているつもりですが、
どうしても前者の'目的1'を解決したい為、何か基本的な所でつまづいてるのでしょうが、
答えが判る方はぜひご教示願います。
尚、VB.netはまだよく判らない為、C#でのご回答をよろしくお願いします。


ちなみに余談ですが、この問題に行き詰ってからはや3日たった状態です(;´Д`A ```


参考にしているURL:
オブジェクトをバイナリファイルにシリアライズ/デシリアライズする
  http://hwm5.gyao.ne.jp/cocoa/csharptips/serialize_binaryfileserialize.htm
Visual C# でデータベースから PictureBox コントロールに画像を直接コピーする方法(SqlServer)
  http://support.microsoft.com/kb/317701/ja

引用返信 編集キー/
■55364 / inTopicNo.2)  Re[1]: MDBに画像を保存した後、読み込んでPictureboxに
□投稿者/ 魔界の仮面弁士 (1965回)-(2010/11/28(Sun) 14:44:21)
No55358 (ももす さん) に返信
> 1.画像(bmp)を取り込む
> 2.Button1を押すと、画像をシリアライズしてbyte配列に格納
File.ReadAllBytes で良いのでは?

> 3.シリアライズしたbyte配列をSQLのInsert文でTestTableに挿入
INSERT INTO TestTable (FileName, IMG) VALUES ('珈琲カップ.bmp', 0x424DA642000000000000A60200002800… )

> 6.データをデシリアライズする ←ここでエラー
MemoryStream に突っ込んでから、Image.FromStream で。
引用返信 編集キー/
■55367 / inTopicNo.3)  Re[2]: MDBに画像を保存した後、読み込んでPictureboxに
□投稿者/ 魔界の仮面弁士 (1966回)-(2010/11/28(Sun) 16:03:33)
No55364 (魔界の仮面弁士) に追記

#region ヘルパーメソッド
static string Dump(string targetFile) {
   byte[] binImg = File.ReadAllBytes(targetFile);
   return BitConverter.ToString(binImg).Replace("-", "");
}
static Image LoadImage(byte[] bin) {
    using (MemoryStream stm = new MemoryStream(bin))
    {
        return Image.FromStream(stm);
    }
}
#endregion

OleDbConnection cn = new OleDbConnection(@"
        Provider=Microsoft.JET.OLEDB.4.0;
        Data Source=C:\db1.mdb;
");
/// <summary>デモ用テーブルの作成</summary>
private void button1_Click(object sender, EventArgs e) {
    cn.Open();
    OleDbCommand cmd = cn.CreateCommand();
    cmd.CommandText = @"
        CREATE TABLE TestTable (
            ID  AUTOINCREMENT(10000, 10)  PRIMARY KEY,
            IMG1 OLEOBJECT NULL,
            IMG2 OLEOBJECT NULL
        );
    ";
    cmd.ExecuteNonQuery();
    cn.Close();
    MessageBox.Show("テーブル作成");
}
/// <summary>SQLにデータを埋め込む</summary>
private void button2_Click(object sender, EventArgs e) {
    cn.Open();
    OleDbCommand cmdINSERT = cn.CreateCommand();
    cmdINSERT.CommandText = @"
        INSERT INTO TestTable (IMG1, IMG2) VALUES (
            0x" + Dump(@"C:\Windows\珈琲カップ.bmp") + @"
           ,0x" + Dump(@"C:\Windows\シャボン.bmp") + @"
        );
    ";
    cmdINSERT.ExecuteNonQuery();
    cn.Close();
    MessageBox.Show("SQLにバイナリを埋め込み");
}
/// <summary>パラメータクエリ</summary>
private void button3_Click(object sender, EventArgs e) {
    cn.Open();
    OleDbCommand cmdINSERT = cn.CreateCommand();
    cmdINSERT.CommandText = @"
        PARAMETERS P1 OLEOBJECT, P2 OLEOBJECT;
        INSERT INTO TestTable (IMG1, IMG2)
        VALUES ( P1, P2 );
    ";
    OleDbParameter P1 = new OleDbParameter("P1", DbType.Object);
    OleDbParameter P2 = new OleDbParameter("P2", DbType.Object);
    cmdINSERT.Parameters.Add(P1);
    cmdINSERT.Parameters.Add(P2);

    P1.Value = File.ReadAllBytes(@"C:\WINDOWS\羽毛.bmp");
    P2.Value = File.ReadAllBytes(@"C:\WINDOWS\大草原の風.bmp");
    cmdINSERT.ExecuteNonQuery();
    cn.Close();
    MessageBox.Show("パラメータクエリでバイナリを渡す");
}
/// <summary>画像読み込み</summary>
private void button4_Click(object sender, EventArgs e) {
    cn.Open();
    OleDbCommand cmdSELECT = cn.CreateCommand();
    cmdSELECT.CommandText = @"
        SELECT TOP 1
            ID, IMG1, IMG2 
        FROM 
            TestTable 
        ORDER BY
            ID DESC
    ";
    OleDbDataReader reader = cmdSELECT.ExecuteReader();
    if (reader.Read()) {
        pictureBox1.Image = LoadImage((byte[])reader.GetValue(1));
        pictureBox2.Image = LoadImage((byte[])reader.GetValue(2));
        MessageBox.Show("ID=" + reader.GetInt32(0));
    }
    cn.Close();
    MessageBox.Show("最後に追加された画像の読み取り");
}

引用返信 編集キー/
■55376 / inTopicNo.4)  Re[3]: MDBに画像を保存した後、読み込んでPictureboxに
□投稿者/ ももす (3回)-(2010/11/28(Sun) 23:14:28)
わぁ!まさにやりたかった事はこれです!
魔界の仮面弁士さん、ありがとうございます!
おかげですっきりしました!


> INSERT INTO TestTable (FileName, IMG) VALUES ('珈琲カップ.bmp', 0x424DA642000000000000A60200002800… )
特に、このデータ(0x…)にする所はまったく頭になかったので、勉強になりました。


それに、コードの書き方が自分とは違って効率の良い書き方をしている点でも勉強になりました。

本当にありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -