電子書籍の厳選無料作品が豊富!

現在、jcode.plを使用したShift JISで構成されていた Perlのcgi を UTF-8 に改造しています。

冒頭で use utf8; を宣言した後、jcode関連の文は、全てコメントアウトしてきました。


複数ある別ファイルからデータ読み込む場合も、

open(IN,"<:utf8","$別ファイル"); という形で、"<:utf8"を挿入して、うまく読みこめています。


ただ、読み込んだ後、別ファイルへUTF-8で書きこむのが、どうしてもうまくいきません。
書きこんだ後、文字化けしてしまいます。

書きこんだファイルを開けてみると、日本語が文字化けしています(アルファベットは大丈夫)


以下のPerlをどのように改造すれば、文字コードをUTF-8で書き込みすることができるのでしょうか?

どうかご教授、よろしくお願い致します。
m(_ _)m

---------------------------------

#-------------------------------------------------
# 編集内容登録処理
#-------------------------------------------------
sub EDITREGIST {

#全角英数字を半角に変換
$zenkaku = '0123456789';
$hankaku = '0123456789';
#Jcode::tr(\$in{'CLICK'}, $zenkaku , $hankaku );

$in{'attach_file'} = &AttachCheck($attach,$attach_name);

#ファイルロック開始
if( $lockkey ne "0" ){ &LOCK; }

if (!open(IN,"<:utf8","$linkdata_file")) { &ERROR( read_linkdata ); }
@BASE = <IN>;
close(IN);

foreach $data (@BASE) {

&LINKDATALIST;

if( $in{'editnum'} eq $CNTNUM ){
if( $in{'attach_file'} eq '' ){
if( $in{'CHDEL'} eq '1' ){
$in{'attach_file'} = ''; unlink("$updir/$IMAGE");
}else{
$in{'attach_file'} = $IMAGE;
}
}else{
unlink("$updir/$IMAGE");
$in{'attach_file'} =~ s/$updir\///g;
}

$in{'LINKNAME'} =~ s/\,/&%/g;
$in{'LINKURL'} =~ s/\,/&%/g;
$in{'LINKURL'} =~ s/&amp;/\&/g;
$in{'COMMENT'} =~ s/\,/&%/g;
$in{'COMMENT'} =~ s/\<br \/\>/!%/g;

if( $in{'CLICK'} eq "" ){ $in{'CLICK'} = 0; }

$new_data = "$CNTNUM,$datenow,$DATE_LMT,$DATE_ESY,$in{'OPN'},$in{'NEWMARK'},$in{'CATEGORY'},$in{'LINKNAME'},$in{'HONORIFIC'},$in{'LINKURL'},$in{'COMMENT'},$in{'CLICK'},$in{'attach_file'},\n";

}else{

$new_data = "$CNTNUM,$DATE_LINKDATA,$DATE_LMT,$DATE_ESY,$OPN,$NEWMARK,$CATEGORY,$LINKNAME,$HONORIFIC,$LINKURL,$COMMENT,$CLICK,$IMAGE,\n";

}
push( @TOTAL,$new_data );
}

#実際にファイルに書き込む
if( !open(OUT,">$linkdata_file") ){ &ERROR( read_linkdata ); }
print OUT @TOTAL;
close (OUT);

#ファイルロック解除
if( $lockkey ne "0" ){ &UNLOCK; }

&SendFinish2;

}

A 回答 (4件)

stdio::getFormDataに対しての見識がないので適切な回答はできませんが、以下を試すとどうなるでしょうか?



%in = ();
stdio::getFormData(\%in,1,"sjis",1,",","$updir/");

を、

use CGI;
%in = map decode_utf8($_), CGI->new->Vars;

に変更。

これで文字化けが解消する可能性はありますが、stdio::getFormDataに詳しい人が回答してくれるかもしれませんので、質問はオープンのままにされたほうがいいと思います。

この回答への補足

N60-BASIC様、Tacosan様、ryu_chan様、誠にありがとうございました。
各皆様のおかげで問題が解決ができまして、大変感謝しております。
今回は、ずばり直ったryu_chan様をベストアンサーとさせて頂きますので、どうぞご了承ください。

実は、もう1つだけ同じ文字化けの現象が起きていて、解決できない問題があります。(もう1つ質問を立てさせて頂ければと思います。

もし宜しければ、再度アドバイスを頂ければと思いますので、どうぞよろしくお願い致します。

補足日時:2011/05/05 18:20
    • good
    • 0
この回答へのお礼

ryu_chanさま
ご教示誠にありがとうございました!

ご指摘の通り、修正したところ、文字化け直りました!!!
m(_ _)m

感動しました!(^^)

まるで魔法のような感じ驚いています。

かれこれ3日間くらい格闘してきましたが、問題が解決できてスッキリしました。

誠にありがとうございました!感謝致します。

お礼日時:2011/05/05 11:52

No.2のTacosanさんが言及されてますが、以下で解決できるかもしれません。



use Encode;

for my $value ( values %in ) {
$value = decode_utf8 $value;
}

この回答への補足

もしくは、別ファイルで行っている以下のデコード処理が問題なのでしょうか?

※sjisの部分はコメントアウトしています。


#-------------------------------------------------
# デコード処理
#-------------------------------------------------
sub DECODE {
if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
else { $buffer = $ENV{'QUERY_STRING'}; }

@pairs = split(/&/,$buffer);
foreach $pair (@pairs) {

($name,$value) = split(/=/, $pair);
$name2 = $name;
$value2 = $value;
$FORM2{$name} = $value;

$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
#半角カナを全角に変換
#Jcode::h2z_sjis(*value);
#文字コード変換
#Jcode::convert(*value,'sjis');

$value =~ s/</&lt;/g;
$value =~ s/>/&gt;/g;
$value =~ s/\n/!%/g;
$value =~ s/\r//g;
$value =~ s/\t//g;
$value =~ s/\,/&%/g;
$value =~ s// /g;

#フォーム変数へ
$in{$name} = $value;
}
}

補足日時:2011/05/05 08:52
    • good
    • 0
この回答へのお礼

ryu_chanさま

ご回答ありがとうございました。
上記コードも試しましたが、文字化けは解消されませんでした(>_<)。


冒頭で以下のような宣言をしていますが、これが問題になっているのでしょうか?

#-------------------------------------------------
# 受け取ったデータの変換
#-------------------------------------------------
%in = ();
stdio::getFormData(\%in,1,"sjis",1,",","$updir/");

お礼日時:2011/05/05 08:48

%in の文字コードか?


Encode::decode でなんとかなるかも....
    • good
    • 0
この回答へのお礼

ご回答ありがとうございました。
早速試してみましたが、ダメでした。

お礼日時:2011/05/05 08:44

惜しいところまで行ってますね。


if( !open(OUT,">$linkdata_file") ){ &ERROR( read_linkdata ); }
を、Perl5の新機能である「3引数open」を使って
if( !open(OUT,">:utf8", $linkdata_file) ){ &ERROR( read_linkdata ); }
としてみたらどうでしょうか?

use utf8; で書かれたスクリプト内文字列や、Encode.pm でデコードされた文字列は、内部utf8表現とでも言うべき特殊な文字列になっています。
この内部utf8表現の文字列は、そのまま標準出力やファイルに対してストリーム出力しようとすると、
Wide character in print at ...
といった感じの警告が出てしまいます。

これを正常にUTF-8で出力するには、内部utf8表現をUTF-8バイトコード文字列に変換してやる必要があります(「内部表現」と言われる理由です)。
本来は出力したい文字列に対してEncode::encode()を明示的に使うのですが、使わなくても自動でやってくれるのが出力オープン時の「:utf8」指定になります。

この辺、仕組みをきちんと理解しようとすると非常にややこしい部分ではあるのですが、一見面倒に見えるこの仕組みのおかげで、文字化け等を気にせずに正規表現などを利用できるようになります。
正確には、内部utf8表現を使うことで「半角英数字以外の文字についてもPerlがすべての文字を1文字単位で扱ってくれるようになる」といったところでしょうか。
興味がありましたら「Perl utf8フラグ」あたりで検索してみるとよいかもしれません。

あと余談ですが、もし前回の私の回答がきっかけでPerl5を勉強してくださってるのだとしたら本当に頭が下がります。
以下のblog記事が「今どきのPerlスクリプト」を知る上で多少参考になるかもしれません。
[ サンプルコードによるPerl入門 - 現代的なPerlの記述方法一覧 ]
http://d.hatena.ne.jp/perlcodesample/20091120/12 …
ご参考まで。
    • good
    • 0
この回答へのお礼

N60-BASIC様

またご回答頂きましてありがとうございました。
m(_ _)m

詳細なご説明でとてもよく分かりました!
参考URLも大変参考になりました!


アドバイス通り

open(OUT,">:utf8", $linkdata_file)

と記載してみました。

正常に動作はしましたが、残念ながら文字化けはまだ直りませんでした。

文字化け状況 → あいうえお 


このPerlは、フォームに日本語等の文字入力して、実行ボタンを押すと

$linkdata_file に、そのデータを書き込みます。

フォームに入力する時は、普通に日本語で表示されていますが、

どうやら、「実行ボタン」を押して、書き込んだ時に文字化けが発生しているようです。

そのため、$linkdata_fileに書き込まれたデータをフォーム上で再編集しようと$linkdata_fileから読み込んだ場合に、文字化けされた文字が反映されてしまうという状況になっています。

なお、ブラウザ上のフォーム自体は、文字コードがutf-8に既にセットされています。

linkdata_file内のデータを除くと、日本語のみが文字化けしていました。

もしかすると原因は、

$in{'LINKNAME'} =~ s/\,/&%/g;
$in{'LINKURL'} =~ s/\,/&%/g;
$in{'LINKURL'} =~ s/&amp;/\&/g;
$in{'COMMENT'} =~ s/\,/&%/g;
$in{'COMMENT'} =~ s/\<br \/\>/!%/g;

の設定にあるのでしょうか?

お手数をおかけいたしますが、ご教示お願いします。
m(_ _)m

お礼日時:2011/05/05 00:05

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!