MySQLにバイナリデータを正常に保存できない

このQ&Aのポイント
  • 保存したいローカルファイルをMySQLにバイナリデータとして格納しようとしていますが、文字エンコードの問題でファイルが壊れてしまいます。
  • MySQLの文字コードはUTF8であり、画像ファイルは正常に表示されますが、xlsやpdfなどのファイルは開けません。
  • 提供されたPerlのコードでは、ファイルデータをバイナリモードで読み込み、DBに格納する処理が行われています。
回答を見る
  • ベストアンサー

MySQLにバイナリデータを正常に保存できない

ローカルに保存してあるファイルをMySQLにバイナリデータとして格納して保存したいと思ってます。 データは格納できるのですが、文字エンコード?の問題でファイルが壊れてしまっているみたいです。 格納後、出力した際にjpgなどの画像は問題なく表示されるのですが、xlsやpdfなどのファイルが開けなくなります。MySQLの文字コードはUTF8です。 #!/usr/bin/perl use DBI; my $dbh = DBI->connect('DBI:mysql:database:localhost:3306', 'user', 'password'); # ファイルパス my $file = '/tmp/test.xls'; # ファイルサイズ my $size = -s $file; # バイナリデータ読み込み my $line; open(IN, $file); binmode(IN); sysread(IN, $line, $size); close(IN); # DBに格納 my $sth = $dbh->prepare(qq|INSERT INTO file_table ( `file_name`, `file_data` ) VALUES (?, ?)|); $sth->execute('test.xls', $line); $dbh->disconnect; 上記のようなコードなのですが、おかしな点があれば教えてください。 よろしくおねがいします。

  • rihm
  • お礼率76% (19/25)
  • Perl
  • 回答数2
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • amane123
  • ベストアンサー率60% (6/10)
回答No.2

>カラム属性のようなもの そうです。 すみません、「BN」ではなく、「BIN」でした。失礼しました。 DBの管理ツールとして「MySQL Workbench」などを使用しているとわかりやすいと思いますが、 「BIN」の他にも「PK」=プライマリキー、「NN」=not nullなどのチェックがあり、そういった設定項目の一つです。

rihm
質問者

お礼

回答ありがとうございます。 BIN=BINARYということですね。ありがとうございます。 WorkBenchを使用してないので普通のMySQLコマンドからではどう表示されるかわかりませんが、BLOB型を指定していたら自動でBINARYつくわけじゃないんですね。 調べていたところ、どうもBLOB型がわるかったらしく(64KBしか格納できない)画像はOKでxlsやpdfがファイル壊れていたのはファイルサイズの問題のようでした。バイナリデータが途中で切られているみたいです。 まだ実際に確認できてはいないのですがもっと大きい型にすればファイル壊れないですむのかな?と思っています。 お手数おかけしました。

rihm
質問者

補足

今手元に環境がないため、 vmwareで環境を作りMySQLに同じスクリプトからデータを突っ込んでみたのですがデータが壊れるということがありませんでした。 default-character-setとかそのあたり現象が発生した環境とは違いがあるのかもしれませんが、今環境がみれないのでそのあたりの違いはわかりません。 ただ気になったのが今作成した環境では日本語ファイル名でも文字化けは起こらず格納されたのですが問題の環境では日本語ファイルだと文字化けして保存されていたことです。 問題の環境は文字コードの設定に問題があるのかもしれません。

その他の回答 (1)

  • amane123
  • ベストアンサー率60% (6/10)
回答No.1

コードの問題ではなくて、カラムの設定の問題だと思います。 「BN」にチェックをつければバイナリデータを正常に保存できたはずです。

rihm
質問者

お礼

回答ありがとうございます。 MySQLのカラムを記載していませんでした。申し訳ありません。 バイナリデータを格納するfile_dataはBLOB型でカラムを作成しています。 BNがよくわからないのですが、カラム属性かなにかでしょうか。

関連するQ&A

  • perlでdb(mysql)に接続

    perlでdb(mysql)に接続し、取得したデータを 表示させるというようなことをしたいのですが、うまく いきません。 ファイル名test.cgi mysqlのバージョンは 5.0.45で 記述は以下です。 #!/usr/bin/perl use DBI; my $dbh = DBI->connect("DBI:mysql:database, "userid", "password"); my $sth = $dbh->prepare('SELECT * FROM tablename'); $sth->execute; print "Content-Type: text/plain\n\n"; print "\n"; while(my @row = $sth->fetchrow_array) { print "$row[0]:$row[1]\n"; } $sth->finish(); $dbh->disconnect(); exit; ブラウザで確認すると何も表示されず、ログとして 以下のエラーが確認できます。 DBD::mysql::st execute failed: Table 'database.tablename' doesn't exist at test.cgi line 8. DBD::mysql::st fetchrow_array failed: fetch() without execute() at test.cgi line 11. my $sth = $dbh->prepare('SELECT * FROM tablename'); で指定したテーブルは存在しておりますし、SQL文の記述も 問題ないと思われます。 また、ファイルのパーミッションは705(755でも同様の結果)です。 perl初心者のため、どこが問題なのか検討がつきません。 ご助言いただきたく存じます。 よろしくお願いいたします!

    • ベストアンサー
    • Perl
  • DBIモジュールと Perl5.8

    Perl5.8のエンコードが理解できずに困っております。 MySQLでは、utf8の文字コードのデータがあります。 以下のスクリプトを実行させると、 Wide character in print at C:/usr/local/site/lib/DBI.pm line 1008. となります。 対処方法はあるのでしょうか? use utf8; use strict; use DBI; my $dbh = DBI->connect("dbi:mysql:dbname=test", "root", "", { AutoCommit=>1, PrintError=>1, RaiseError=>1} ); my $fname = "test.txt"; my $sth = $dbh->prepare("select id, namae from test order by id asc;"); $sth->execute(); # 出力ファイルを開く。 open FILE, ">" , $fname or die "Can't open $fname: $!"; # 整形された結果をファイルにダンプする。 my $rows = $sth->dump_results(80, "\n", ",", \*FILE); # 出力ファイルを閉じる。 close FILE or die "Error closing result file: $!\n"; $dbh->disconnect();

    • ベストアンサー
    • Perl
  • MySQLのトランザクションについて

    初めて質問します。 今、PerlのDBIを使ってMySQLのトランザクション処理にチャレンジしています。 ところが、rollback処理がうまくできません。 具体的には、 table2 がある状態で下のプログラムを動かすと、 エラーの表示が出るのに、 table1 は作成されました。 何らかのエラーがあれば、どちらも作成されないようにしたいです。 ======================================================= my %sql; $sql{db_name} = "database"; $sql{host} = "localhost"; $sql{user_name} = "user_name"; $sql{password} = "password"; use DBI; my $dbh = DBI->connect('DBI:mysql:'.$sql{db_name}.':'.$sql{host}, $sql{user_name}, $sql{password} ,{RaiseError => 1, PrintError => 0, AutoCommit => 0 }) || &Err(); my $sth; my $re; eval { my $sql_string1 = "create table table1(`id` int);"; my $sql_string2 = "create table table2(`id` int);"; $sth = $dbh->prepare($sql_string1); $re = $sth->execute; $sth = $dbh->prepare($sql_string2); $re = $sth->execute; }; if ($@) { $tag="Err:".$@."\n"; $sth = $dbh->rollback; }else{ $sth = $dbh->commit; } $sth->finish; $dbh->disconnect; ======================================================= 検索して、いろいろいじっても解決しませんでした。 どうかよろしくお願いします。

    • ベストアンサー
    • Perl
  • mysql 最大値 取得 

    mysqlのデータベースから、列の最大値を取り出したいのですが、 以下のように書いているのですが、取得される値が1しか返ってこないです。 間違っているところはあるでしょうか? perlで書いています。 my $dbh = DBI->connect("DBI:mysql:host=${db_host};database=${db_name}", $db_user, $db_pass); my $sth = $dbh->prepare("SELECT MAX(列名) FROM テーブル名"); my $rv = $sth->execute(); print "$rv";

    • ベストアンサー
    • MySQL
  • Mysqlの接続について

    現在、以下のようなperlのスクリプトを作っているのですが、mysqlへの接続,切断は以下の場合、どちらにした方がいいのでしょうか? (1)の場合 use DBI; $dsn="DBI:mysql:database=dbname:host=localhost"; $dbh=DBI->connect($dsn,'user','pass'); $sth = $dbh->prepare("SELECT no,title,name,date,host From `table1` where no='1'"); $sth->execute; $sth->fetchrow_array; $sth->finish; $sth2 = $dbh->prepare("SELECT no,title,name,date,host From `table2` where no='1'"); $sth2->execute; $sth2->fetchrow_array; $sth2->finish; $dbh->disconnect; (2)の場合 use DBI; $dsn="DBI:mysql:database=dbname:host=localhost"; $dbh=DBI->connect($dsn,'user','pass'); $sth = $dbh->prepare("SELECT no,title,name,date,host From `table1` where no='1'"); $sth->execute; $sth->fetchrow_array; $sth->finish; $dbh->disconnect; $dsn="DBI:mysql:database=dbname:host=localhost"; $dbh=DBI->connect($dsn,'user','pass'); $sth2 = $dbh->prepare("SELECT no,title,name,date,host From `table2` where no='1'"); $sth2->execute; $sth2->fetchrow_array; $sth2->finish; $dbh->disconnect; (1)の場合と(2)の場合の違いは、(1)の場合、最初にデータベースに接続して、一番最後に切断する事で、(2)の場合、毎回データベースへの接続と切断を行う事が違います。 (2)の場合、毎回接続と切断を行うので、2回ほどではあまり変わらないかもしれないのですが、もし10回とか接続と切断を行うとかなり負荷が高くなるような気がするのですが、他のHPなどを拝見すると接続をしたら切断を行うように癖をつけるようにした方がいいと書かれていたりします。 どちらの方が正しいやり方というか、負荷がすくなく使えるのでしょうか?

    • ベストアンサー
    • Perl
  • PerlでMySQLのテーブル一覧取得

    PerlでMySQLのデータベース内のテーブル一覧を取得することはできますか? 自分で以下の様なサブルーチンを作りましたが、返り値に何も入っていませんでした。 コマンドラインでもshow tables;で確認したのでテーブルは確実に存在します。 接続も showでfetchrow_arrayなどは使えないのでしょうか? またselect文でテーブル一覧を取得する方法がありましょうか? Error: failed to connect to DB.とは出てこないので、接続も成功しています。 sub mysql_tablesGet{ my @data=@_; my $db_id = $data[0]; my $db_password = $data[1]; my $dbh = DBI->connect("dbi:mysql:dbname=".$ftp_id.";host=$mysql_host", $db_id,$db_password) or die "$!\n Error: failed to connect to DB.\n"; my $sth = $dbh->prepare("show tables;"); $sth->execute; my @response; my $i=0; while(my @var = $sth->fetchrow_array){ my ($table_name) = $var[0]; $response[$i] = $table_name; $i++; } $dbh->disconnect; return @response; } MySQLのログはこんなのが出ています。 130406 17:11:44 70 Connect test2@192.168.11.22 on test2 70 Query set autocommit=1 特にエラーは出ていないので、show tables;は成功していると思います。

    • ベストアンサー
    • Perl
  • perlからMySQL5に接続できません

    WindowsでperlからMySQLに接続できません。 perlは以下のようなものです。 結果は「1」と表示されるので、MySQLへの接続ができていないのだと思います。 考えられる原因がわかる方、アドバイスをお願いします。 #!/Perl/bin/perl use DBI; print "Content-type: text/html\; charset=shift_jis\n\n"; print "1"; my($dbh, $sth); $dbh = DBI->connect("DBI:mysql:database=データベース名;host=127.0.0.1", "root", "rootのパスワード",{ RaiseError => 1, AutoCommit => 0 }); print "2"; $sth = $dbh->prepare("select * from テーブル名;"); 以下略 WindowsXP SP2 Apache2.2.4 ActivePerl5.8.8 MySQL5.0

    • ベストアンサー
    • MySQL
  • PerlからMysqlに接続してデータを昇順?降順に並べる方法

    こんばんは。 現在、PerlからMysqlに接続してデータを昇順?降順に並べようと思っております。 しかし、降順に並べる場合、うまく動きません。 詳細を以下に明記しますので、どなたか宜しくお願いします。 テーブル名:test テーブル内のデータ:100個 まず、昇順の場合 少し省略しますが、まず接続します。 $dbh = DBI->connect($dsn,$user,$password); $sth = $dbh->prepare("SELECT * From test Order by no limit 5,2"); $sth->execute; $sth->finish; $dbh->disconnect; これで、no5から二つ(つまり、no5とno6のみ)が抽出されると思います。 降順の場合 $dbh = DBI->connect($dsn,$user,$password); $sth = $dbh->prepare("SELECT * From test Order by no desc limit 5,2"); $sth->execute; $sth->finish; $dbh->disconnect; こうすると、no6,no5という順に抽出されます。ちなみに、limit 5,2をlimit 5,3とすると、no6,no5,no4と抽出されます。なぜここでlimit 5,2の際にno5,no4でlimit 5,3の際にno5,no4,no3という順に抽出されないのか分かりません。 私がしたいのは、noを降順(no5,no4,no3・・・)という順に表示させたいのです。ただ、降順に表示させるのではなく、例えば上記でlimitで指定したように、あるnoから3つとかしたいのです。 質問が長くなり分かりにくいかも知れないのですが、どなたか力を貸していただけないでしょうか。 宜しくお願いします。

    • ベストアンサー
    • Perl
  • perlとmysqlの接続について。 mac

    いつもお世話になっております。 現在、perlとmysqlの接続について苦戦しています。 私の状況としては Mac osx 10.6.6 使用3ヶ月。 プログラムを独学で勉強し始めて2ヶ月弱。 習熟進度としては 「初めてのperl」ある程度わかる。2週は読んだ。 「すぐわかるオブジェクト指向Perl」1週読んだ。 なんとなくわかる。 という状況です。 昨日より、MySQL(GPL)をダウンロードして挑戦しています ネットに置いてあったソースコードで、 #!/usr/bin/perl use DBI; my $dbh = DBI->connect("DBI:mysql:futomi", "futomi", "password"); my $sth = $dbh->prepare("SELECT * FROM test"); $sth->execute; print "Content-Type: text/plain\n\n"; print "\n"; while(my @row = $sth->fetchrow_array) { print "$row[0]:$row[1]\n"; } $sth->finish(); $dbh->disconnect(); exit; という形でperlからmysqlをつなごうとしているのですが、 install_driver(mysql) failed: Can't locate loadable object for module DBD::mysql in @INC というエラーメッセージと Perhaps a module that DBD::mysql requires hasn't been fully installed というエラーメッセージが表示されます。 cpanからDBD::mysqlもダウンロードし、Makefile.PL・・・コンパイルでよろしいのでしょうか?も終わっており、DBD::mysqlとDBIも@INK上に設置していると思われるのですが、 一向に接続する事ができません。 どのように対処すれば接続する事ができるのでしょうか? ご説明いただければと思います。 また、足りない文章、ソース等がありましたらそれらもあげさせていただきますので、 なにとぞご協力くださいませ。 それでは失礼いたします。

    • ベストアンサー
    • Perl
  • MYSQL 4.1 の余計なエスケープ処理

    おはようございます。PERL 5.8.5 からMYSQL4.1 サーバーへのデータINSERT 時の文字変換処理について教えてください。 MYSQL 4.1 の文字コードは次の通りです。 SHOW VARIABLES LIKE 'character?_set?_%'; の結果 character_set_client :binary character_set_connection:binary character_set_database:utf8 character_set_results:binary character_set_server:utf8 character_set_system:utf8 MYSQL 4.1 サーバーが上記のような状態で、PERL で次の処理をします。なお、PERL ソース自体はEUC で書かれています。 #!/usr/bin/perl use Jcode; use DBI; $string = "あああ"; Jcode::convert( ?$string, 'utf8', 'euc' ); $dbh = DBI->connect( 'DBI:mysql:DB名:ホスト名:3306', 'ユーザー名', 'パスワード' ,{AutoCommit => 0} ); $sth = $dbh->prepare( "set names utf8" ); $sth->execute; $sth->finish; $sth = $dbh->prepare( "insert into test values( ? )" ); $sth->bind_param( 1, $string ); $sth->execute; $sth->finish; $dbh->commit; $dbh->disconnect; 上記のソースを実行すると、MYSQL 4.1 サーバーには [あ?あ?あ] のような、余計なエスケープが掛かった状態で文字がINSERT されているのです。 私としては、set names utf8 で、MYSQL 4.1 サーバーとクライアントで同様の文字コードを使うようにしているので、MYSQL 4.1 における余計な文字コード変換はないものと思っています。余計な文字コード変換がないにもかかわらずエスケープ文字が入る理由が分かりません。 この現象についてお分かりの方がいらっしゃいましたら教えて頂きたく思います。なお、ネットでも調べたのですが、どの方も未解決でしたので質問さえて頂きました。 お願いします。

専門家に質問してみよう