ishiducaの日記 このページをアンテナに追加 RSSフィード

2008-11-04

[][][]Encode::find_encodingを使って文字コードを変換する 11:01 Encode::find_encodingを使って文字コードを変換する - ishiducaの日記 を含むブックマーク はてなブックマーク - Encode::find_encodingを使って文字コードを変換する - ishiducaの日記 Encode::find_encodingを使って文字コードを変換する - ishiducaの日記 のブックマークコメント

前のエントリー:http://perl.g.hatena.ne.jp/ishiduca/20081102/1225609360 :内部処理しないで文字コードを変換する]を書いた後に、otsune さんから find_encoding を使ったほうが速いですよ。と教えていただいたので使ってみました。

が、その前に、間違いがあったので訂正します。

 × # utf-8 から Shift_JISに変換

 ○ # Shift_JIS から utf-8 に変換

さて、前回と同じ事を find_encoding(文字コード) を使ってやってみる。

>perl
use strict;
use LWP::Simple;
use Encode;

my $uri = 'http://www.digitalside.net/bbs2/blog.html';
my $html = decode('Shift_JIS',get($uri));

my $enc_object = find_encoding("utf-8");
print $enc_object->encode($html);

成功。

ただ、どういう仕組みかよくわからないので、ググってみたら 弾さんが書いてました。引用するのが面倒なので、http://blog.livedoor.jp/dankogai/archives/50815457.html 404 Blog Not Found:perl tips - Encodeを速く使う方法 を参照してください...だけでは、ぼんやりしてしまうのでちょっとだけ。

  • Encode::find_encoding(文字コード) は文字コード変換用の器(オブジェクト)を生成する
  • decodeメソッドで任意の文字列のデコードを行う
  • encodeメソッドで任意の文字列のエンコードを行う

...まちがってたらすみません。

最後の2行について

my $enc_object = find_encoding("utf-8"); # 文字コード変換用(ただし utf-8 のみ)を生成
print $enc_object->encode($html);        # $html を utf-8 でエンコードして出力

print encode("utf-8", $html);

と同じことをやってると考えていいのかな、と思います。

さて、次に失敗例

> perl
use strict;
use LWP::Simple;
use Encode;

my $uri = 'http://www.digitalside.net/bbs2/blog.html';
my $html = get($uri);

my $enc_object = find_encoding("utf-8");
print $enc_object->encode($html);

当たり前の話ですが、デコードしていない(Shift_JIS から Unicode文字列 に直していない)ので、当然文字化けします。

さて、最初の例で my $html = decode('Shift_JIS',get($uri)); を使っているんですが、せっかくなので decode(文字コード, $str) の代わりに find_encoding を使ったやり方も書いてみます。

> perl
use strict;
use LWP::Simple;
use Encode;

my $uri = 'http://www.digitalside.net/bbs2/blog.html';
my $html = get($uri);

my $enc_sjis = find_encoding('Shift_JIS');
my $enc_utf8 = find_encoding('utf-8');
print $enc_utf8->encode($enc_sjis->decode($html));

成功。

otsune さん、ありがとうございました。

otsuneotsune2008/11/04 13:15さらに
encode("utf-8", $html)

encode_utf8($html)
のほうが。

ishiducaishiduca2008/11/04 16:06ありがとうございます><

ishiducaishiduca2008/11/04 20:01JSON形式で出力したデータは、こんな感じで利用する。
http://ishiduca.sakura.ne.jp/doc/kakakudot.html

別に新しい事は何もないけど、まあ。

SialanSialan2012/11/01 21:21This is the percfet way to break down this information.

ytyoqgcytyoqgc2012/11/02 10:31WwhIl8 <a href="http://gaodiuhpidxj.com/">gaodiuhpidxj</a>

hwhjkkegaplhwhjkkegapl2012/11/02 15:03INGVWA , [url=http://jkhcdhoytizz.com/]jkhcdhoytizz[/url], [link=http://bjqoywtvimij.com/]bjqoywtvimij[/link], http://ilbzqbfywozx.com/

swkohnswkohn2012/11/04 23:42IaCvAU <a href="http://ryxbhqjtcdzd.com/">ryxbhqjtcdzd</a>

yhrprweyhrprwe2012/11/05 12:57XbVWkx , [url=http://jvseelphdmet.com/]jvseelphdmet[/url], [link=http://lvnpyyjiggzm.com/]lvnpyyjiggzm[/link], http://fhxoysrrjagh.com/

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20081104

2008-11-02

[][]内部処理しないで文字コードを変換する 16:02 内部処理しないで文字コードを変換する - ishiducaの日記 を含むブックマーク はてなブックマーク - 内部処理しないで文字コードを変換する - ishiducaの日記 内部処理しないで文字コードを変換する - ishiducaの日記 のブックマークコメント

内部処理しないで文字コードを変換するなら Encodeモジュールの Encode::from_to($str, '処理前の文字コード' => '処理後の文字コード') を使った方が楽

ためしに「DigitalSide ザ・ステレオ屋」の更新ページは 'Shift_JIS' なので、これを 'utf-8' に直してみる。

参考:http://www.digitalside.net/bbs2/blog.html: DigitalSide ザ・ステレオ屋 AudioBlog]

> perl
use strict;
use LWP::Simple;
use Encode;

my $uri = 'http://www.digitalside.net/bbs2/blog.html';
my $html = get($uri);

# utf-8 から Shift_JISに変換
Encode::from_to($html, 'Shift_JIS' => 'utf-8');

print $html;

成功。

otsuneotsune2008/11/03 13:30from_toは重いので
my $enc_object = find_encoding("Shift_JIS");
でOOなEncodeオブジェクトを作っておいて

print $enc_object->encode($html);

でencodeする手法を覚えちゃうのがいいかも。

ishiducaishiduca2008/11/03 21:36>> otsune さん
ありがとうございます。
早速試してみたいと思います。記事の
> # utf-8 から Shift_JIS に変換

> # Shift_JIS から utf-8 に変換
の間違いでしたので、
my $enc_object = find_encoding("utf-8");
print $enc_object($html);
なんですね。

BaieBaie2014/05/07 08:31I'm relaly into it, thanks for this great stuff!

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20081102

2008-10-29

[][][]EUC-JPの文字列のファイルを読み込んで、処理をしてUTF-8で出力する その1 失敗 16:47 EUC-JPの文字列のファイルを読み込んで、処理をしてUTF-8で出力する その1 失敗 - ishiducaの日記 を含むブックマーク はてなブックマーク - EUC-JPの文字列のファイルを読み込んで、処理をしてUTF-8で出力する その1 失敗 - ishiducaの日記 EUC-JPの文字列のファイルを読み込んで、処理をしてUTF-8で出力する その1 失敗 - ishiducaの日記 のブックマークコメント

  • euc-jpでエンコードした任意のテキストファイル 'test.txt'
  • perlスクリプトは 'utf-8' で書いたものと 'euc-jp' で書いたもの 二つ用意する
  • 'use utf8' で嵌る点を探ってみる

まず、'test.txt' の中身

日本語

perlのコード

#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use Encode;

my $log = 'test.txt';

open( my $fh, "<", $log ) or die("can not open $log: $!");
my $line = <$fh>;
close( $fh );

$line = decode('euc-jp', $line);
$line =~ s/語/人/;
print encode('utf-8', $line);

'utf-8' で保存したもので実行すると

> perl encodetest.pl

# [結果]
> 日本人

成功。つづいて 'euc-jp' で保存したもので実行すると

> perl encodetest.pl

# [結果]
Malformed UTF-8 character (unexpected continuation byte 0xb8, with no preceding start byte) at enctest.pl line 15.
Malformed UTF-8 character (1 byte, need 3, after start byte 0xec) at enctest.pl line 15.
Malformed UTF-8 character (unexpected continuation byte 0xbf, with no preceding start byte) at enctest.pl line 15.
Malformed UTF-8 character (1 byte, need 2, after start byte 0xcd) at enctest.pl line 15.
日本語

失敗。'use utf-8' は 'UTF-8'で書かれたコードでないと駄目っぽい。


参考

なので、'use utf8' の代わりに 'use encoding' を使う

EUC-JPで保存された場合は use encoding 'euc-jp', STDOUT => 'utf-8' を使う

#!/usr/bin/perl

use strict;
use warnings;
use encoding 'euc-jp', STDOUT => 'utf-8';
# EUC-JP で書かれたコードの内部で扱う文字リテラルを Unicode文字列 に扱い
# 標準出力時に UTF-8 で出力する
# $_ = decode('euc-jp', $_);
# print encode('utf-8', $_);
# みたいなもんか
use Encode;

my $log = 'test.txt';

open( my $fh, "<", $log ) or die("can not open $log: $!");
my $line = <$fh>;
close( $fh );

$line = decode('euc-jp', $line);
$line =~ s/語/人/;
print $line;
> perl encodetest.pl

# [結果]
> 日本人

ついでに...

use encoding 'euc-jp'; として STDOUT => 'utf-8'; を削って print $line; を print encode('utf-8', $line); とすると、エラーがかえってくる

"\x{0097}" does not map to euc-jp at enctest.pl line 16.
"\x{00a5}" does not map to euc-jp at enctest.pl line 16.
"\x{009c}" does not map to euc-jp at enctest.pl line 16.
???\x{0097}\x{00a5}???\x{009c}?̏????돢?

同じような例は、↓にあった

[][][]UTF-8の文字列を処理してUTF-8で出力する その1 失敗 14:32 UTF-8の文字列を処理してUTF-8で出力する その1 失敗 - ishiducaの日記 を含むブックマーク はてなブックマーク - UTF-8の文字列を処理してUTF-8で出力する その1 失敗 - ishiducaの日記 UTF-8の文字列を処理してUTF-8で出力する その1 失敗 - ishiducaの日記 のブックマークコメント

  • macbookのターミナルはデフォルトでUTF-8に設定したもの(つまり、このコードはUTF-8
  • 'にほんご' を 'えいご' に変換して、出力する(つもり)
> perl
use strict;
use warnings;
use utf8;
# 以下は UTF-8の文字リテラルとして扱うようになる
use Encode;

my $str = 'にほんご';
$str =~ s/にほん/えい/;

# このままだと 'Wide character in print at - line' とおこられるのでエンコードする
print encode('utf-8', $str);

# [結果]
> えいご

これは成功。次、失敗例

> perl
use strict;
use warnings;
use Encode;

my $str = 'にほんご';
my $uni = decode('utf-8', $str);
$uni =~ s/にほん/えい/; # ここがまずい
print encode('utf-8', $uni);

# [結果]
> にほんご

んで、こうした

> perl
use strict;
use warnings;
use Encode;

my $str = 'にほんご';
my $uni = decode('utf-8', $str);
my $org = decode('utf-8', 'にほん'); # マッチングテストする文字列もデコード
my $rep = decode('utf-8', 'えい');   # 同上
$uni =~ s/$org/$rep/;
print encode('utf-8', $uni);

# [結果]
> えいご

成功。結構嵌った

tokuhiromtokuhirom2008/10/29 17:26use encoding 'euc-jp';

LuiizLuiiz2012/08/20 09:17I'm so glad I found my sotluion online.

zxlvfibzxlvfib2012/08/20 19:09urWEMK <a href="http://jjvttpbkwbxf.com/">jjvttpbkwbxf</a>

duhckkvduhckkv2012/08/24 22:0491ON07 , [url=http://zsixfgrcjonw.com/]zsixfgrcjonw[/url], [link=http://izhprwlalzjv.com/]izhprwlalzjv[/link], http://nzdgjulpapwp.com/

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20081029