• ベストアンサー

ファイルの入出力

あるフォルダにはいっているすべてのcsvファイルのデータをひとつのテキストファイルに出力したいのですが、うまくいきません。 わからなかったのでとりあえず、別々のファイルで下記を 実行してみました。 ■指定のフォルダに入っているファイル名をすべて出力。 これはうまくいきました。csvファイルが3つほど入っているのですが、 3つのファイル名が出力されます。 #!/usr/bin/perl opendir(IN,"test/"); while ($filename = readdir(IN)) { $path = "C:/perl/test/$filename"; $source = $filename; print $source,"\n" if -f $path; } ■指定のファイル(a.csv)の中身をtest.htmlとしてファイル出力 これもうまくいきました。カンマ区切りのデータが、 行ごとにあるだけはいっていき、htmlのテーブルにがつがつはいっていきます。 #!/usr/bin/perl my $source = "a.csv"; open (IN, $source) or die "$!"; my $dest = "test.html"; open (OUT, ">$dest") or die "$!"; print OUT '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis" /> <title>無題ドキュメント</title> <style type="text/css"> <!-- .style1 {color: #FFFFFF} --> </style> </head> <body> <table width="419" height="105" border="0" cellpadding="0" cellspacing="0"> <tr> <th bgcolor="#000000"><span class="style1">名前</span></th> <th bgcolor="#000000"><span class="style1">住所</span></th> <th bgcolor="#000000"><span class="style1">性別</span></th> </tr>'; while (<IN>) { chomp; @data = split(/,/, $_); print OUT "<tr>\n"; print OUT "<th bgcolor=\"#666666\">",$data[0],"</th>\n<td>",$data[1],"</td>\n<td>",$data[2],"</td>\n"; print OUT "</tr>\n"; } print OUT "</table> </body> </html>"; つまり、この二つを1ファイルにまとめたいのです。 一個目で取得したファイル名リストを 2個目のopen で順次ファイルの中身を取っていってほしいのです。 いったんファイル名をテキストファイルに出力してから、 それを読む方法もあったのですが、 できたら、ファイルを出力せずに変数からそのまま、 ファイル名の一覧を取得したいと思っています。 どなたか教えていただけますでしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
  • metis
  • ベストアンサー率52% (86/165)
回答No.1

#!usr/bin/perl opendir(DIR,"test/"); $dest = "test.html"; open (OUT, ">$dest") or die "$!"; while ($filename = readdir(DIR)) { $path = "test/$filename"; $source = $filename; if(-f $path){ open (IN, $path) or die "$!"; print OUT '<!DOCTYPE html PUBLIC (以下、表の1行目が終わるまで略) while (<IN>) { chomp; @data = split(/,/, $_); print OUT "<tr>\n"; print OUT "<th bgcolor=\"#666666\">",$data[0],"</th>\n<td>",$data[1],"</td>\n<td>",$data[2],"</td>\n"; print OUT "</tr>\n"; } close(IN); } } closedir(DIR); (3行略) close(OUT); こんな感じでしょうか。 ポイントは ・1つ目のでファイルを見つけるごとに2つ目の処理を実行する。 ・出力先ファイルは先に開いておいて、最後まで閉じない この辺りでしょうか。 詳しくはソースの違いを良く見て理解して下さい。 自分でひとつにまとめた時(動かなかったものですね)のソースも手元に置いて、比較すればなお良しです。 分からなければ補足しますが。 ちなみに、コードには、私なりのスタイルが入っててその辺りごっちゃになってますが、まぁ、何とかなるかと思います。

trfnc223
質問者

お礼

ご回答ありがとうございます! 考え方は理解できたような気がします! whileを入れ子にするんですね。 ちょっと試してみます! もしかしたらまたおたずねするかもしれません。 その時はどうかよろしくお願いします。。。。

その他の回答 (1)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

検索対象のディレクトリには .csv以外のファイルもなかったりしないのでしょうか? あと、ディレクトリを再帰的に潜って行くこともしないでいいのですよね? opendirで自分でディレクトリエントリを読んで行くとファイルの振り分け とかが面倒だと思うので、globを使ってみました。 #!/usr/bin/perl use strict; use warnings; my $targetdir = shift || 'test'; my @filelist =glob( $targetdir . '/*.csv' ); open my $of, '>', 'output.html' or die; print $of <<END_OF_HEADER; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "?http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">? <html xmlns="?http://www.w3.org/1999/xhtml">? <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis" /> <title>無題ドキュメント</title> <style type="text/css"> <!-- .style1 {color: #FFFFFF} --> </style> </head> <body> <table width="419" height="105" border="0" cellpadding="0" cellspacing="0"> <tr> <th bgcolor="#000000"><span class="style1">名前</span></th> <th bgcolor="#000000"><span class="style1">住所</span></th> <th bgcolor="#000000"><span class="style1">性別</span></th> </tr> END_OF_HEADER foreach my $file (@filelist) { open my $if, '<', $file or warn "can't open $file"; while (<$if>) { my @fields = split q{,}, $_; print $of <<END_OF_TEMPLATE; <tr> <th bgcolor="#666666">$fields[0]</th> <td>$fields[1]</td> <td>$fields[2]</td> </tr> END_OF_TEMPLATE } close $if; } print $of <<END_OF_TRAILER; </table> </body> </html> END_OF_TRAILER close $of; ヘッダとかトレイラーのところはサブルーチンにしたいところですが とりあえずはこんなところで。

trfnc223
質問者

お礼

ご回答ありがとうございます! なにぶん初心者なものでglobというものを使ったことがなかったのですが、 とりあえず実行してみたらきれいにできました。 いただいたコードをひもといて自分で勉強したいと思います! ありがとうございました!!