文字コードがShift-JISのCSVファイルを読み込み、UTF-8のテキストファイルに出力するのに
プログラムの中で変更しようとしているのですが、うまくいきません。出力ファイルの文字コードを
確認するとShift-JISのままです。
どなたか教えていただけないでしょうか?
ActivePerl v5.16.0を使用し、Encodeモジュールのfrom_toを使用しています。
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Encode;
my $input_file="input.csv";
my $output_file="output.txt";
open (IN, $input_file) or die "$!";
open (OUT, ">$output_file") or die "$!";
while (<IN>){
chomp ($_);
my @data=split(/,/,$_);
for(my $i=0;$i<@data;$i++){
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8'); #Shift-JISからUTF-8に変換
$data[$i]=~s/\s+//g;
print OUT $_;
}
print OUT "\n";
}
close (IN);
close (OUT);
No.5ベストアンサー
- 回答日時:
あの、私のや他の回答をよく読んで考えてください。
for(my $i=0;$i<@data;$i++){
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8'); #Shift-JISからUTF-8に変換
$data[$i]=~s/\s+//g;
print OUT $_;
}
この部分は **** $_には何の影響も与えません ****
よって、** 出力に関することだけに注目したら **
for(my $i=0;$i<@data;$i++){
print OUT $_;
}
これと等価です。どこで「Shift_JIS からUTF-8へ変換」してますか?
$_は「while (<IN>){」の<IN>で1行読み込まれ、「chomp ($_);」で末尾の改行コードが削除されただけで、移行なにも変化していません。コードは入力のまま=Shift_JISです。それをそのまま出力すればShift_JISになるのが正解です。
しかも、項目数分だけ繰り返し出力されます。
(重複行になる、と#1に書いたのはchompのことを失念していた私のミスです)
@dataを変更したのなら、出力するのは@dataでしょう。
join(",", @data)とすれば、項目をカンマ区切りの文字列にすることができます。
あと#2にあったfrom_toの使い方。マニュアルをよく読みましょう
http://perldoc.perl.org/Encode.html#[$length-=]-from_to($octets,-FROM_ENC,-TO_ENC-[,-CHECK])
・$octetsを直接変換する
・$octetsの長さを返す
とあります。つまり
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8')
だと,$data[$i]には元の内容は破棄されて、文字列の長さになってしまいます。
各項目毎に処理したい、という意図はわかりました。
ですが、文字コードの変換が項目毎に違うなんてことはまず無いでしょう。
それならば、$_で1行をコード変換→splitして項目毎の処理、としてもいいのでは?
ついでにPerlIOを使って
open (IN, "<:encoding(shift_jis)", $input_file) or die "$!";
open (OUT, ">:utf8", $output_file) or die "$!";
とでもやれば、プログラム中はコードをあまり意識せずに文字列処理ができます。
kmeeさん
詳しい親切な回答ありがとうございます。
勉強になりました。
Encode:from_toについて書いてあった何人かのHPを読んでいて
同じ使い方をやっていたとのそれを鵜呑みにしてしようしていました。
これからはPerldocを参考にしたいと思います。
本当にありがとうございました。
No.4
- 回答日時:
んーー・・・読めない人なのかねー
本質的に以下と同じことをしてるって指摘されてるんだけどなー
$a=1;
$b = $a + 1;
print $a; ## $aに1を足してるのになぜか 1 って表示されるっ!?
もしかして,@dataを$_のリファレンスみたいなものだと思ってる?
#nkfとかiconvを使う方がいいかもね.
No.2
- 回答日時:
#1 で何を言われたのか理解できているんでしょうか?
このプログラムは入力をほぼそのまま出力しています. つまり, 「文字コードがShift-JISのCSVファイルを読み込」んだら「出力ファイルの文字コードを確認するとShift-JISのまま」なのは当然です. むしろ, このプログラムでなぜ「UTF-8のテキストファイルに出力する」と思ったのでしょうか?
実際のプログラムが (特に出力の部分で) こうなっていないというなら, 実際のプログラム (に近いもの) を出してください.
あと, 「文字コードの変換方法」について勘違いしている. Encode::from_to の使い方を確認してください.
この回答への補足
Tacosanさん
回答ありがとうございます。
質問したプログラムは単に文字コードがShift-JISである入力ファイルを文字コードがUTF-8である出力ファイルに変換するプログラムを作成したいだけです。
私が考えたのは下の箇所で
for(my $i=0;$i<@data;$i++){
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8'); #Shift-JISからUTF-8に変換
$data[$i]=~s/\s+//g;
print OUT $_;
}
(別に1行ずつencodeすればよかったですが、)
Shift-JISのデータをUTF-8のデータに変換でき、UTF-8の出力ファイルに格納できると
思っていましたができませんでした。
何かいいやりかたはありますか?
No.1
- 回答日時:
> my @data=split(/,/,$_);
で$_を分割して新しく作った@dataに対して処理しているのですから
@dataを変更しても $_には影響ありません。
・現状、同じ行が複数出力されていませんか?1行の項目数分、$_の出力を繰り返すのですから。
・そもそもsplitする意味はあるのでしょうか?
この回答への補足
kmeeさん
いろいろ不備があり、すいません。このプログラムの目的はカンマ区切りになっている項目をそれぞれ抽出し、いろいろ手を加えたいと思っているため、そうなっています。その部分はうまくいっていて、今は文字コードの部分だけがうまくいかない状況です。
言葉足らずですいませんでした。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
awkスクリプトでダブルクォーテ...
-
log2の「正確な」計算方法
-
sprintfについて
-
DOSコマンドで、標準出力を出力...
-
ExcelをCSV書き出す場合のシー...
-
バッチファイルの作り方(CSV→...
-
VBAでCSVファイルを途中行まで...
-
テキストファイルの各行を配列...
-
エクセルVBA コードが同じでも...
-
close()で例外が投げられる理由
-
vba dir の相対パス
-
fopenでディレクトリ内の全ファ...
-
unlink 、renameが使えない理由
-
batファイルでrenameができませ...
-
Perlの変数に文字数制限(容量...
-
XML::Parserの parsefileの結果...
-
openした後、closeしないでプロ...
-
C言語でファイル名を取得
-
FindFirstFileとFindNextFileで...
-
htaccessで特定のディレクトリ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
awkスクリプトでダブルクォーテ...
-
エクセルVBAで素数だけを出力す...
-
DOSコマンドで、標準出力を出力...
-
sprintfについて
-
重複するデータを抽出できる秀...
-
教えて!perlから.exeファイル...
-
自動更新
-
[Perl]ファイル出力のエンコー...
-
Rubyを使ってtelnetで実行した...
-
文字コードの変換(Shift-JISか...
-
Perlからsyslog経由でログを出...
-
無名配列にスライスを使いたい。
-
Perl内でJavaScri...
-
perlでの文字列抽出
-
Perl<->Oracle間での文字化けに...
-
PerlからのCSV出力
-
ファイル出力の改行コードをLFに
-
機器のI/OをArduinoでSDに記録...
-
コンソール出力をテキストに出...
-
Perlでエラーログに日時をつける
おすすめ情報