文字コードで行き詰まりました。
同じUTF8で全く同じ文字列であるにも関わらず(外見上は全く同じにも関わらず)、2つの生の文字コードが異なるということが起きて、どうしたらいいのかわかりません。
WEBサイトから「あいう」という文字を取り出してきて、そいつの文字コードを、生で表示させました。
すると、
E38182E38184E38186
になります。ところが、perl文の中で$testStr="あいう";
として、そいつを同じように16進数で表示させると、
304230443046
と、違うものになっています。
にも関わらず、「WEBからとってきた文字列」も「perl内で書いた文字列」も両方「Jcode::getcode()」でその文字コードを調べると、utf8になります。
しかも、それら両方とも、print()をすると、同じように「あいう」と表示されます。
「perl内で書いた文字列」の方では、問題なくDBに入れれるのですが、「WEBからとってきた文字列」の方は、文字化けします。
「WEBからとってきた文字列」を「perl内で書いた文字列」のような文字コードに変換するにはどうすればよいのでしょうか?
なぜ同じUTF8として認識されているのでしょうか?
もう気が狂いそうです。
どなたかお助けください。お願いします。
環境
Ubuntu
perl v5.8.8 built for x86_64-linux-gnu-thread-multi
以下は詳しいソースです。
use utf8;#この質問に関係がありそうなモジュールです
use Jcode;
use DBI;
use URI;
use YAML;
use Switch;
use Web::Scraper;
use HTTP::Request::Common;
use LWP::UserAgent;
use HTTP::Cookies;
use HTTP::Request::Common qw(POST);
##Webサイトから文字列「あいう」を取得してくる。取得過程は略してます。
$testStrFromWeb=@titleArr[$i];#ちなみにWebサイトの文字コードはUTF8です。
print("testStrFromWeb:".$testStrFromWeb);#「あいう」と表示されます。
##Webサイトから得た文字列「あいう」の生の文字コードを表示。
$strCode=$testStrFromWeb;
$strCode =~ s/(.)/sprintf "%X", ord($1)/eg;
print "$strCode\n";#E38182E38184E38186と表示されます
##Webサイトから文字列「あいう」の文字コードの種類を表示(utf8が返ってくる)
my $getcode = Jcode::getcode(\$testStrFromWeb);
print $getcode ,"\n";#utf8と表示される
##perl内で書いた文字列。
$testStrInPerl="あいう";
print("testStrInPerl:".$testStrInPerl);#「あいう」と表示されます。
##perl内で書いた文字列「あいう」の生の文字コードを表示。
$strCode=$testStrInPerl;
$strCode =~ s/(.)/sprintf "%X", ord($1)/eg;
print "$strCode\n";#304230443046と表示されます
##perl内で書いた文字列「あいう」の文字コードの種類を表示
my $getcode = Jcode::getcode(\$testStrInPerl);
print $getcode ,"\n";#utf8と表示される
ここまで読んでくださってありがとうございます。
No.1ベストアンサー
- 回答日時:
2つの文字列の違いはutf8フラグがついているかいないかです。
utf8フラグはperlが文字列として解釈できる内部コードに付くフラグなので、
内部コードであるか、そうでないかの違いと言うこともできます。
内部コード(utf8フラグがついた文字列)にはutf8が使われていますが、
utf8フラグの有無で挙動が変わるので、
実際にはutf8フラグがついた内部コードと、utf8フラグがついていないutf8バイト列は
別物と考えた方が分かりやすいです。
別物なので、外部から取ってきたデータがutf8のバイト列なら、
ちゃんとperlの内部コードに変換しなければなりません。
具体的には、
my $decodedStrFromWeb = Encode::decode("utf8", $testStrFromWeb);
として、utf8を内部コードにデコードします。
デコードすることでperlはそれを文字列として解釈できるようになります。
逆に内部コードを外部(ファイルなど)に出力するときには、
内部コードからutf8などにエンコードすることが望ましいです。
PerlIOレイヤを使えば、このようなエンコード・デコード処理はある程度透過的に行えます。
なお、内部コードが出現するべき文脈で
内部コード以外のバイト列(utf8フラグが付いていない文字列のこと)が出現した場合、
perlはそのバイト列を内部コードに自動的に変換します。
しかし、この自動変換ではバイト列をlatin-1文字コードによる文字列と見なしてdecodeするため
たいていの場合予想外の変換結果になり文字化けしたように見えます。
例えば、
$utf8_flag . $no_utf8_flag;
の様な文字列連結を行う場合、utf8フラグが付いていない文字列が自動変換されるので、
$utf8_flag . Encode::decode("latin-1", $no_utf8_flag);
と書いたのと同じ事になります。
###Sample###
use utf8;
use strict;
use Jcode;
use Encode;
# ※標準出力にUTF8で出力する(PerlIOレイヤ)
#binmode STDOUT, ":utf8";
# utf8フラグが付いていないバイト列
my $testStrFromWeb=Encode::encode("utf8","あいう");
#↓「あいう」と表示される。ただし※のコメントを外すと文字化けする。
print "testStrFromWeb:".$testStrFromWeb."\n";
#↓文字化けする。
print "testStrFromWebを表示:".$testStrFromWeb."\n";
my $strCode=$testStrFromWeb;
$strCode =~ s/(.)/sprintf "%X", ord($1)/eg;
#↓E38182E38184E38186と表示される
print "$strCode\n";
my $getcode = Jcode::getcode(\$testStrFromWeb);
#↓utf8と表示される
print $getcode ,"\n";
# UTF-8を内部形式にデコードすれば、$testStrInPerlと同様に扱える。
my $decodedStrFromWeb = Encode::decode("utf8", $testStrFromWeb);
# utf8フラグが付いている文字列(=perlの内部形式)
my $testStrInPerl="あいう";
#↓「あいう」と表示される。
print "testStrInPerl:".$testStrInPerl."\n";
my $strCode=$testStrInPerl;
$strCode =~ s/(.)/sprintf "%X", ord($1)/eg;
#↓304230443046と表示される
print "$strCode\n";
my $getcode = Jcode::getcode(\$testStrInPerl);
#↓utf8と表示される
print $getcode ,"\n";
###End###
[参考]
Perl 5.8.x Unicode関連
http://www.rwds.net/kuroita/program/Perl_unicode …
UTF8 フラグあれこれ - daily dayflower
http://d.hatena.ne.jp/dayflower/20080219/1203493 …
Wernerさん、どうもこんなに早く、そして丁寧に教えてくださってありがとうございます。
誰も回答してくれなかったら本当に狂いそうでしたが、おかげさまでうまくいくことができました。そして文字コードトラブルの根本的理解にもなりました。
結局、
my $decodedStrFromWeb = Encode::decode("utf8", $testStrFromWeb);
がこの問題を直接解決する文になりました。
ここまで親切に解説していただくと、なぜかやる気までUpしてきましたw
本当にありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
準・究極の選択
「年収1000万円で一生カレーライス」か 「年収180万円で毎日何でも食べ放題」 あなたはどちらを選びますか?
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
エクセルに詳しい方に教えて頂きたいです。 全く同じ文字に見えるのにEXACT関数を使って調べるとFA
Excel(エクセル)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
perlのlwp::simpleのgetのprint...
-
perlで読み込むテキストの文字...
-
UTF_16で取得しUTF_8で出力した...
-
EC-CUBEでの文字化け
-
perl でエラー:Wide character...
-
デバッグ情報が文字化けする
-
CSVファイルの中で、「 , 」カ...
-
エクセルで数値を全角文字(カ...
-
英数字のみ全角から半角に変換
-
CString から LPCTSTRの型に変換
-
文字コードの%E3%80%とは何です...
-
住宅にカナを入力する際に丁目...
-
「何とかで始まり、何とかで終...
-
カンマ区切りの数字をCSVフ...
-
Excelについて質問です。 セル...
-
C#で、テキストボックスの入力...
-
カンマ区切り
-
VBA 文字に半角が含まれて...
-
プログラミングでは、半角括弧...
-
SJIS->UTF8->SJISコード変換に...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
perl でエラー:Wide character...
-
【LaTeX】pBibTeXでのエラーの...
-
MFCのコントロールにUTF-8の文...
-
CGIでメール送信で件名文字化け
-
Jcodeによるカタカナ→ひらがな変換
-
WindowsでUTF-8のPerlスクリプ...
-
Java+MySQLで特殊文字(丸数字(...
-
【文字コード】外見上は全く同...
-
デバッグ情報が文字化けする
-
Cannot decode string with wid...
-
HTML::Templateでutf-8のテンプ...
-
Jcode.pmでconvertできない
-
perl について
-
カタカナ一覧表が知りたい
-
JcodeモジュールとEncodeモジュ...
-
sedやperlでの2バイト文字を含...
-
オブジェクト? perlをオーバー...
-
UTF-8のPerlから、UTF-8、EUC、...
-
pythonの文字コードとファイル操作
-
WWW::Mechanizeの文字コードに...
おすすめ情報