iRSSの日記

はてなダイアリーiRSSの日記の続き

Wide character in print at ...

この「Wide character in print at ...」には、何度も、悩まされては、
理解するのだが、のど下過ぎると、わすれちゃう。

再復習。

printするときに、utfフラグがついているのがいかんです。

Wide character in print at ..のメッセージがでる原因は,print対象の文字列にutf8フラグがついているということ

#!/usr/bin/perl -w
use strict;
use warnings;
use utf8;
my $str = 'あああ';
print $str;

↑これを実行すると

Wide character in print at ... line 6.

なんてメッセージがでます。


対策としては

#!/usr/bin/perl -w
use strict;
use warnings;
use utf8;
my $str = 'あああ';
utf8::encode($str);
print $str;

$strについた,utf8フラグをこれで明示的に落とせる。
こうするか

#!/usr/bin/perl -w
use strict;
use warnings;
my $str = 'あああ';
print $str;

use utf8;を最初からつけない。
これで、'あああ'はutf8文字列はみなされなくなる。

use utf8をつけないということでいいかと思うのですが
eucをutf8に変換したりするときに、このフラグがついたりするのです。
これが、やっかいで、わすれがち。

printするまえとか、encodeした直後に、フラグをはずしてあげればOKそう。

#!/usr/bin/perl -w
use strict;
use warnings;
use Encoding;
use utf8;
my $str = 'あああ';
$str = Encode::encode('utf-8',$str);
print $str;

↑こうすると、フラグをはずすことができ、Wide character in print at ...はでない

#!/usr/bin/perl -w
use strict;
use warnings;
use Encoding;
#use utf8;
my $str = 'あああ';
$str = Encode::encode('utf-8',$str);
print $str;

しかし↑このように、$strにutfフラグがついていないのに、Encode::encode('utf-8',$str);をしてしまうと、出力結果は文字化けてしまう。フラグがあるときのみEncode::encode('utf-8',$str);すべし。

#!/usr/bin/perl -w
use strict;
use warnings;
use Encoding;
#use utf8;
my $str = 'あああ';
$str = Encode::encode('utf-8',$str) if utf8::is_utf8($str);
print $str;

これでOK。



utf8::is_utf8では実際の文字列がUTF-8かどうかではなく、あくまでフラグがついているかどうかを確認します。そのため、UTF-8の文字列もフラグが付いていなければ上記の出力はno flagとなります。またutf8::is_utf8はuseしなくても使用できる。useすると全然違う意味あいになるので注意。


UTF-8フラグが付いていたら、encodeを使用してフラグをはずします。以下の例では$stringをutf-8に変換して出力します。
print encode('utf-8', $string);

まとめ

printする前に、文字列にutfフラグをはずしておきましょう。

$str = Encode::encode('utf-8',$str) if utf8::is_utf8($str);
print $str;

こんな感じにしておけば、OK

こんな曲者にも注意

decode と from_to 同じようだが、utf8フラグのたつたたないが、異なる。

警告: 次の呼び出しは全く同じに見えますが、完全に等しくはありません。

from_to($data, "iso-8859-1", "utf8"); #1
$data = decode("iso-8859-1", $data); #2

#1 と #2 の両方は完全に有効なUTF-8文字列を $data に設定します。しかし、 #2 だけがutf8フラグをつけます。 #1 と等価な呼び出しは以下のようなものです。

$data = encode("utf8", decode("iso-8859-1", $data));