
文字コードが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を見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
テキストファイルから日本語部...
-
Perlでファイルの末尾から指定...
-
Windowsで複数のファイルを同じ...
-
close()で例外が投げられる理由
-
エクセルVBA コードが同じでも...
-
バッチファイルの作り方(CSV→...
-
VB6.0でDB接続する際に切断時の...
-
ファイル全てを .xlsm に変更し...
-
batファイルでrenameができませ...
-
csvファイルの横方向への改行に...
-
VBAでCSVファイルを途中行まで...
-
ディレクトリ名を取得したい
-
コマンドプロンプトからperlを...
-
perlをwindows環境でshift-jis...
-
MATLAB グローバル変数の宣言
-
パスから最後のディレクトリだ...
-
drtファイルはどうしたら開...
-
VBでファイル分割の方法
-
C言語で特定の行を抽出する方法...
-
動かなくなったのでJavaソース...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
awkスクリプトでダブルクォーテ...
-
大量メールの任意のヘッダだけ...
-
sprintfについて
-
文字化け
-
重複するデータを抽出できる秀...
-
sprintfで10進数を桁数指定で16...
-
foreachによるカウント方法
-
IEのリロードボタンを押すとデ...
-
2つ質問があり、まず1つ目な...
-
SYSログ出力時の文字化けについて
-
C言語の問題について
-
同じ文なのにちがうように表示...
-
特殊文字の数を調べる
-
DOSコマンドで、標準出力を出力...
-
ドメインからIPアドレスあるい...
-
log2の「正確な」計算方法
-
自動更新
-
CSVファイルのダウンロードにつ...
-
Perl<->Oracle間での文字化けに...
-
この記述というのは?
おすすめ情報