
文字コードが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で質問しましょう!
似たような質問が見つかりました
- CGI htmlからパラメータで、cgiに渡したい。 1 2023/02/06 16:15
- Excel(エクセル) エクセルのVBAについて とあるサイトのコードを参考に、CSVの文字化けを直すVBAを作成しているの 7 2022/11/04 14:15
- その他(プログラミング・Web制作) pythonのこのエラーがわかりません 3 2022/11/16 14:54
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- その他(プログラミング・Web制作) python 2 2022/12/23 09:06
- Ruby 教えてください 2 2023/01/04 17:50
- 英語 英語ができる方に質問です。 以下の文がネイティブの方に伝わるかどうかを確認していただけないでしょうか 7 2022/12/16 14:54
- CGI perlで書いたcgiでsqliteの使い方を教えてください 2 2023/05/08 21:29
- C言語・C++・C# [至急]Project Euler:#17Number letter countsコード入力出力解説 2 2022/09/24 02:46
- その他(プログラミング・Web制作) Pythonを勉強しています。 5 2023/08/25 09:51
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
awkスクリプトでダブルクォーテ...
-
文字化け
-
Perl<->Oracle間での文字化けに...
-
コンソール出力をテキストに出...
-
sprintfについて
-
ExcelをCSV書き出す場合のシー...
-
MATLAB グローバル変数の宣言
-
エクセルVBA コードが同じでも...
-
Perlで特定行から特定行までを...
-
Windowsで複数のファイルを同じ...
-
Perlの変数に文字数制限(容量...
-
fgets で値が取得できない
-
ファイル全てを .xlsm に変更し...
-
Perl-CGI で排他制御はどうすれ...
-
ディレクトリー内のリスト出力...
-
ファイルの結合
-
VBA テキストファイルを読み取...
-
絶対+相対アドレスから絶対ア...
-
2つのCSVファイルをマッチング
-
batファイルでrenameができませ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
重複するデータを抽出できる秀...
-
awkスクリプトでダブルクォーテ...
-
sprintfについて
-
DOSコマンドで、標準出力を出力...
-
文字コードの変換(Shift-JISか...
-
Perl<->Oracle間での文字化けに...
-
[Perl]ファイル出力のエンコー...
-
エクセルVBAで素数だけを出力す...
-
データの選択
-
apacheの動作について
-
「print関数は出力先のファイル...
-
教えて!perlから.exeファイル...
-
ファイル出力の改行コードをLFに
-
PerlからのCSV出力
-
Active Perlでsleepを使う。
-
[awk]uniq -cで複数ファイルの...
-
バッチファイルで、記号を含む...
-
EUCで出力されるプログラムをS-...
-
htmlから、ファイル、もしくはC...
-
リファレンスについて。
おすすめ情報