
文字コードで行き詰まりました。
同じ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で質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
- JavaScript フォームが空欄の時にフォームの外をクリックすると、エラーが出るコードを調べています。 1 2023/06/25 11:51
- Java Javaの問題なのですが、「3文字以上の英数字文字列を入力し、文字列の中に文字(9)が出てくるまでの 1 2023/06/06 18:55
- Visual Basic(VBA) VBA B列にある前から10文字のみ表示 3 2023/08/07 11:24
- Visual Basic(VBA) エクセルVBAについて 2 2023/01/31 16:21
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
- C言語・C++・C# C言語の質問です。 以下の命令を実行するプログラムを作りました ①文字列aとbの長さを表示 ②aとb 1 2022/04/29 15:35
- HTML・CSS リンクバナーのHTMLタグ。画像を変えたり、設置位置を変えるとバナー貼付け側はどう見える? 2 2023/02/01 12:01
- JavaScript Javascriptが機能せず原因が分からないので教えて頂きたいです 3 2023/06/04 14:50
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
perl でエラー:Wide character...
-
perlについての質問
-
住宅にカナを入力する際に丁目...
-
テキストエリアの改行を変換(...
-
URL末のスペースを削除したいの...
-
CSVファイルの中で、「 , 」カ...
-
正規表現
-
初めてのAIプログラミング C言...
-
Perlで一行で文字列の置き換え
-
Perlでのマッチング処理について
-
1つのセルに1つ以上のデータ...
-
掲示板の管理者画面でログイン...
-
タグを正規表現で完全に削除
-
このHPのアドレスバーの区切り...
-
複数行に渡る文字列の置換
-
ダブルクォーテーション置換時...
-
VBAでの全角数字と半角数字の判...
-
/ [ 【 の文字をマッチさ...
-
ファイル名の右側を変更したい ...
-
Perlでの文字列置換
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
perl でエラー:Wide character...
-
MFCのコントロールにUTF-8の文...
-
【文字コード】外見上は全く同...
-
printfの書式指定での2バイト文...
-
【LaTeX】pBibTeXでのエラーの...
-
デバッグ情報が文字化けする
-
perlについての質問
-
漢字コードについて
-
カタカナ一覧表が知りたい
-
Jcode.pmでconvertできない
-
Jcodeによるカタカナ→ひらがな変換
-
オブジェクト? perlをオーバー...
-
jcode.plのかわり
-
HTML::Templateでutf-8のテンプ...
-
Perlにおけるパターンマッチ
-
UTF-16からUTF-8への変換
-
UTF8コードでのメール送信
-
EC-CUBEでの文字化け
-
sedやperlでの2バイト文字を含...
-
Python データの可視化
おすすめ情報