• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:テキストファイルの処理について)

テキストファイルの処理について

このQ&Aのポイント
  • 初心者のためテキストファイルの処理に困っています。fgets、file_put_contents、str_replace、arrayなどの関数を使えば処理できると思いますが、構文がわかりません。参考になるサイトやアドバイスを教えてください。
  • テキストファイルの処理についてアドバイスがほしいです。具体的には、テキストファイルの整形や特定の行の削除などの処理を行いたいです。どのような関数を使えばいいでしょうか。アドバイスをお願いします。
  • テキストファイルの処理について質問です。初心者であり、PHP5を学んでからまだ50時間ほどしか経っていません。具体的な処理方法や関数の使用方法について教えていただけますか。参考になるサイトやアドバイスがあれば教えてください。

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

  • ベストアンサー
  • think49
  • ベストアンサー率59% (285/482)
回答No.3

えっと…、ごめんなさい。 改めて試したところ、#2のコードにミスがあることがわかりました。 × $array = split("[\n{2,}]",$file); \n{2,} としなければ空行にマッチできませんし、何よりShift_JISやUTF-8だと改行は \r\n でした。 #2では \nで区切られてしまうため、CSVになるときの行単位ではなく、セル単位で配列化してしまっています。 このため、以降のコードが全て正常に動かないのです…。 余計な回り道をさせてしまって申し訳ないです。 以下にサンプルコードを作りましたので、参考にしてください。(今度は検証したので動くはずです…) <?php $file = file_get_contents('test01.txt'); $file = mb_convert_encoding($file, "UTF-8", "auto"); // preg用にUTF-8に文字コード変換(preg系はUTF-8にすると全角文字を扱える正規表現として機能します) /* 行単位の配列に (1次元配列) */ $array = preg_split("/(?:\r\n){2,}/m", $file); // 空行区切りで分割 /* セル単位の配列に (2次元配列) */ foreach($array as &$value){ $value = preg_split("/\r\n/", $value); // CSVのセルデータに分割 (配列の値を更に配列に。ここで2次元配列になります) } /* CSV形式に変換 */ foreach($array as &$value){ $value = preg_replace('/"/', '""', $value); // ダブルクオートをエスケープ $value = preg_replace('/^.*$/', '"$0"', $value); // セルデータ全体をダブルクオートで括る $value = implode(',', $value); // 2次元配列→1次元配列 } $output = implode("\r\n", $array); // 1次元配列→文字列 $output = mb_convert_encoding($output, "Shift_JIS", "auto"); // Shift_JIS文字コードに header('Content-Type: text/plain; charset=Shift_JIS'); // Content-Typeヘッダ出力 echo $output; // 出力 ?> > *”,”だけの行が削除できない。 "," は区切り文字なので、値に持ちたい場合はエスケープする(安全な文字に変換する)必要がありますね。 この場合CSVを読み込むプログラムによってエスケープ方法が変わります。 念のため確認しますが、完全なCSV形式でいいのですか? つまり、読み込むプログラムはExcelと思ってよいですか? 上のコードはExcelで読む前提で書いています。 PHPで読むなどしていて "," のエスケープ方法が特殊だとそれに準拠した形にする必要があります。 ちなみに、掲示板で使われるCSVでは改行は <br> に、"," はHTML文字実体参照にすることが多いですね。 CSVファイルフォーマットの解説:CodeZine http://codezine.jp/article/detail/2364 > *”円”があったら新しいテキストファイル(test02.txt)上で改行 > (質問の7.次の行と次の次の行は削除) 配列にしてしまえば後は簡単です。 - 配列の値をpreg_replaceしてNULL(空データ)にする - preg_matchでチェックしてから unset() のいずれかで対応してください。 あと、サンプルでは省略した「セルの順番変更」ですが、2次元配列にする以前にやった方がわかりやすいと思います。 echo preg_replace('/^(\d{4})(\d{2})(\d{2})$/', '$1/$2/$3', "20090520"); // 出力 こんな感じで括弧を使って必要な部分をキャプチャし、変数で並び替えてみてください。

すると、全ての回答が全文表示されます。

その他の回答 (3)

  • think49
  • ベストアンサー率59% (285/482)
回答No.4

#3の補足です。 「"," をエスケープする必要がある」と書きましたが、#3では「全データをダブルクオートで括る」形式にしています。 ダブルクオートで括ることで、「"," をエスケープする」のではなく「'"' をエスケープする」に変化します。 Excelで出力するCSVは「改行を含む」または「カンマを含む」データ限定でダブルクオートで括っていますが、 全データをダブルクオートで括ってもExcelで読み込むことが出来ます。(それでもCSVフォーマットに準拠しているので)

idek
質問者

お礼

何から何まで、本当にすいません。 感謝にたえません。 今度こそ出来るよう頑張ります。 取り急ぎ御礼まで。

idek
質問者

補足

出来ました。 ありがとうございました。 2行目と21行目に下記メッセージが出ました。 Warning: mb_convert_encoding() [function.mb-convert-encoding]: Unable to detect character encoding $file = mb_convert_encoding($file, "UTF-8", "auto");→ $file = mb_convert_encoding($file, "UTF-8", "Shift_JIS"); header('Content-Type: text/plain; charset=Shift_JIS'); → //header('Content-Type: text/plain; charset=Shift_JIS'); で解決しました。 教えていただいたプログラムは、一行ずつ意味を解釈し勉強してみます。 私はVB6で育った世代で、配列の概念が極めて希薄だと教えていただいた中で感じています。 *VBだと1行ずつ読んでその中で処理しworkファイルに落とす、ような感じになると思います。 重ね重ねありがとうございました。 深謝しています。 最後に完成したソースを貼っておきます。 <?php $file = file_get_contents('test01.txt'); $file = mb_convert_encoding($file, "UTF-8", "Shift_JIS"); // preg用にUTF-8に文字コード変換(preg系はUTF-8にすると全角文字を扱える正規表現として機能します) /* 行単位の配列に (1次元配列) */ $array = preg_split("/(?:\r\n){2,}/m", $file); // 空行区切りで分割 /* セル単位の配列に (2次元配列) */ foreach($array as &$value){ $value = preg_split("/\r\n/", $value); // CSVのセルデータに分割 (配列の値を更に配列に。ここで2次元配列になります) } /* CSV形式に変換 */ foreach($array as &$value){ $value = preg_replace('/"/', '""', $value); // ダブルクオートをエスケープ $value = preg_replace('/^.*$/', '"$0"', $value); // セルデータ全体をダブルクオートで括る $value = implode(',', $value); // 2次元配列→1次元配列 } $output = implode("\r\n", $array); // 1次元配列→文字列 $output = mb_convert_encoding($output, "Shift_JIS", "auto"); // Shift_JIS文字コードに //header('Content-Type: text/plain; charset=Shift_JIS'); // Content-Typeヘッダ出力 echo $output; // 出力 file_put_contents("test02.txt","$output"); ?> ---完成したソース <?php $file = file_get_contents('test01.txt'); $file = mb_convert_encoding($file, "UTF-8", "auto"); // preg用にUTF-8に文字コード変換(preg系はUTF-8にすると全角文字を扱える正規表現として機能します) /* 行単位の配列に (1次元配列) */ $array = preg_split("/(?:\r\n){2,}/m", $file); // 空行区切りで分割 /* セル単位の配列に (2次元配列) */ foreach($array as &$value){ $value = preg_split("/\r\n/", $value); // CSVのセルデータに分割 (配列の値を更に配列に。ここで2次元配列になります) } /* CSV形式に変換 */ foreach($array as &$value){ $value = preg_replace('/"/', '""', $value); // ダブルクオートをエスケープ $value = preg_replace('/^.*$/', '"$0"', $value); // セルデータ全体をダブルクオートで括る $value = implode(',', $value); // 2次元配列→1次元配列 } $output = implode("\r\n", $array); // 1次元配列→文字列 $output = mb_convert_encoding($output, "Shift_JIS", "auto"); // Shift_JIS文字コードに header('Content-Type: text/plain; charset=Shift_JIS'); // Content-Typeヘッダ出力 echo $output; // 出力 ?>

すると、全ての回答が全文表示されます。
  • think49
  • ベストアンサー率59% (285/482)
回答No.2

初心者であることを卑下することはないと思いますよ。 わからないなりに工夫して試した跡が見られるので、私は逆に向上心のある初心者さんだと思っています。 > $array = preg_replace("/^(\s)*(\r|\n|\r\n)/m", ",", $array);; 恥ずかしながら preg_replace が配列を引数に持てるということを知りませんでした。これならforeachが不要になります。 すみません、余計に混乱させてしまいましたね。 私の環境では下記コードでほぼ期待通りの結果になりました。 <?php $file = file_get_contents('test01.txt'); $array = split("[\n{2,}]",$file); $array = preg_replace("/(?:\r\n|[\r\n])/", ",", $array); header('Content-Type: text/plain; charset=UTF-8'); // Content-Typeヘッダ出力 print_r($array); ?> # header() は「テキストとして扱うため + 文字コード指定で文字化けを防ぐため」です。 # 省略できるなら省略しちゃっても構いません。

idek
質問者

お礼

>私は逆に向上心のある初心者さんだと思っています。 教えていただいた上に、励ましの言葉まで頂き、ありがとうございます。 深謝しています。

idek
質問者

補足

下記ソースを書きました。 ---下記ソース <?php $file = file_get_contents('test01.txt'); $array = split("[\n{2,}]",$file); $array = preg_replace("/(?:\r\n|[\r\n])/", ",", $array); //header('Content-Type: text/plain; charset=sjis'); // Content-Typeヘッダ出力 $text_work = implode("\r\n", $array); //echo $text_work; file_put_contents("test02.txt","$text_work"); ?> ---下記ソース以上 最終行の"test02.txt"には、最初の'test01.txt'と同ほぼじものが出力されてしまいます。 (10,000円が10改行000円改行が違うだけ) *”各配列の値に対してpreg_replace を使って1行のCSVに変換し、配列の値を上書きします。” →これは、出来ているのだと思います。 *”,”だけの行が削除できない。 *”円”があったら新しいテキストファイル(test02.txt)上で改行 (質問の7.次の行と次の次の行は削除) 何かアドバイスいただけると幸いです。 度々すいません。

すると、全ての回答が全文表示されます。
  • think49
  • ベストアンサー率59% (285/482)
回答No.1

「テキスト→CSV」の変換を行いたい、ということですね。 > fgets,file_put_contents,str_replace,array等の関数を使い処理するのだと思います。 必要な関数はわかっているようですので、ポイントだけ説明します。 未検証につき細かなミスがあるかもしれませんが、考え方(アルゴリズム)だけ受け取ってください。 1. テキストファイル取得 file_get_contents で受け取り、変数に格納します。 この際、trimで前後の空行を取り除くと良いと思います。 2. 空行で区切り、配列に分割格納する CSV変換後の1行は空行区切りのブロックと捉えて良さそうです。 split で空行(\n{2,})を区切り文字に指定して、各ブロックを配列に分割格納します。 3. preg_replace でCSV形式に変換する 2. で作成した配列を foreach で処理をループさせます。 各配列の値に対してpreg_replace を使って1行のCSVに変換し、配列の値を上書きします。 4. implodeで配列から文字列に戻す implode で区切り文字に改行(\n)を指定して、文字列に戻します。 5. file_put_contents で書き込み 完成です。 PHP: file_get_contents - Manual http://jp.php.net/manual/ja/function.file-get-contents.php PHP: file_put_contents - Manual http://jp.php.net/manual/ja/function.file-put-contents.php PHP: trim - Manual http://jp.php.net/manual/ja/function.trim.php PHP: split - Manual http://jp.php.net/manual/ja/function.split.php PHP: foreach - Manual http://jp.php.net/manual/ja/control-structures.foreach.php PHP: preg_replace - Manual http://jp.php.net/manual/ja/function.preg-replace.php PHP: implode - Manual http://jp.php.net/manual/ja/function.implode.php # file_get_contentsを知っていたのに、file_put_contentsを知らなかった…。 # PHP5からの関数だから見逃していたのかな。

idek
質問者

お礼

早速参考マニュアルサイトまで書いていただきありがとうございます。 私のスキルからすると、かなり高度な事をやっているようです。 大変感謝しています。取り急ぎ御礼まで。

idek
質問者

補足

初心者ですいません。 >3. preg_replace でCSV形式に変換する >2. で作成した配列を foreach で処理をループさせます。 >各配列の値に対してpreg_replace を使って1行のCSVに変換し、配列の値を上書きします。 > >4. implodeで配列から文字列に戻す >implode で区切り文字に改行(\n)を指定して、文字列に戻します。 > >5. file_put_contents で書き込み >完成です。 上記3の部分でうまくいきません。 「preg_replace を使って1行のCSVに変換し」が組み立てられないのだと思います。 3,4,5の参考例文のようなもの、アドバイス、いただけると幸いです。 ---私のソース <?php $file = file_get_contents(('test01.txt')); //$file = preg_replace("/^(\s)*(\r|\n|\r\n)/m", "", $file); $array = split("[\n{2,}]",$file); foreach ($array as $key => $value) { $array = preg_replace("/^(\s)*(\r|\n|\r\n)/m", ",", $array);; } print_r($array); ?> ---私のソース以上 ---print_rの表示の一部 Array ( [0] => , [1] => , [2] => , [3] => , [4] => 植物の光合成 [5] => 理科 [6] => 3 [7] => 相田ももこ [8] => 7月4日(土) [9] => 10:00~13:00 [10] => 30名 ---print_rの表示の一部以上 test01.txtは、最初に投稿したものと同じです。

すると、全ての回答が全文表示されます。

関連するQ&A