テキストファイルの読み込みについて - PHPプロ!Q&A掲示板

2863

  • 0P

テキストファイルの読み込みについて

質問日時 / 2010年9月11日 05:00 (最終編集:9月11日 08:19)    回答数 / 10件

Questioner:  reika_ciruela  このエントリーをはてなブックマークに追加 

キーワード / ファイルの読み込み    feof    fgets   

txtファイルをフォームで読み取り、置換してhtmlファイルに変換したいのですが、
fgets()やfile_get_contents()での読み込みを試してみましたが、エラーが出てできません。

独学で勉強中の素人のものなので恥かしいですが、以下がソースです。
どなたかアドバイスお願いします。

fgets()のエラー
Warning: fopen(testlog.txt) [function.fopen]: failed to open stream: No such file or directory in C:\xampp\htdocs\test\convert.php on line 60

Warning: feof() expects parameter 1 to be resource, boolean given in C:\xampp\htdocs\test\convert.php on line 61

Warning: fgets() expects parameter 1 to be resource, boolean given in C:\xampp\htdocs\test\convert.php on line 62

以下 line 61 と line 62 のエラーが永遠と繰り返されます

file_get_contents()のエラー
Warning: file_get_contents(testlog.txt) [function.file-get-contents]: failed to open stream: No such file or directory in C:\xampp\htdocs\test\convert.php on line 60

■テスト用txtファイル(testlog.txt)
  1. [2010/08/18 23:43:14] ハンドルネーム: 発言内容
  2. [2010/08/18 23:43:22] ハンドルネーム: 発言内容
  3. [2010/08/18 23:43:22] ハンドルネーム: 発言内容
  4. [2010/08/19 21:23:50] ハンドルネーム: 発言内容
  5. [2010/08/19 21:24:07] ハンドルネーム: 発言内容
  6. [2010/08/20 21:25:03] ハンドルネーム: 発言内容

fgets()版phpファイル(convert.php)
  1. <?php
  2.   if (isset($_POST['file']) == FALSE){
  3. ?>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  8. <title>チャットログ(Skype)変換ツール</title>
  9. <style type=text/css>
  10. <!--
  11.   body {
  12.     background: #fffff;
  13.     font-size: 90%;
  14.     font-family:;
  15.   }
  16.   td.info {
  17.     font-size: 12px;
  18.   }
  19.   h1 {
  20.     font-size: 120%;
  21.     text-align: center;
  22.   }
  23. -->
  24. </style>
  25. </head>
  26.     <body>
  27.   <h1>txt→html<br />チャットログ(Skype)変換ツール</h1>
  28.   <form action=convert.php method=POST >
  29.     <table width=100% cellspacing=12><tr align=center>
  30.     <td><table border=0 width=480>
  31.     <tr align=left>
  32.     <td>タイトル:</td>
  33.     <td><input type=text name=title /></td>
  34.     <td class=info>※チャットのテーマタイトルをどうぞ。<br />&nbsp;&nbsp;&nbsp;</td>
  35.     </tr>
  36.     <tr align=left>
  37.     <td>ファイル:</td>
  38.     <td><input type=file name=file /></td>
  39.     <td class=info>※htmlファイルに変換したい<br />&nbsp;&nbsp;&nbsp;txtファイルを選択してください。</td>
  40.     </tr>
  41.     </table></td>
  42.     </tr>
  43.     <tr align="center">
  44.     <td><input type=submit value=変換  /></td>
  45.     </tr>
  46.     </table>
  47.   </form>
  48.   </body>
  49. </html>
  50. <?php
  51.     } else {
  52.     $ftitle = $_POST['title'];
  53.     $fdata = $_POST['file'];
  54.     $pathinfo = pathinfo($fdata);
  55.     $fname = $pathinfo['filename'];
  56.     header("Content-Disposition: attachment; filename= $fname.html");
  57.     mb_internal_encoding("UTF-8");
  58.  
  59.     /* ファイルの読み込み */
  60.     $fp = fopen($fdata,'rb');
  61.     while (feof($fp) == FALSE) {
  62.       $str = fgets($fp);
  63.       $str = mb_convert_encoding($str"UTF-8""Shift_JIS, EUC-JP, UTF-8");
  64.     }
  65.     fclose($fp);
  66.     /* ファイルの読み込み終わり */
  67.  
  68.     preg_match_all("/\d{4}\/\d{2}\/\d{2}/",$str,$dateArry)
  69.     $date = array_unique($dateArry[0])
  70.  
  71.     /* 置換スタート */
  72.     $rekakko1 = preg_replace("/\[/",'</td></tr><tr valign="top"><td align="center" width="20">',$str);
  73.     $redate = preg_replace("/\d{4}\/\d{2}\/\d{2}\s(?!\d{2}\:\d{2]\:\d{2})/",'[',$rekakko1);
  74.     $rekakko2 = preg_replace("/\]\s/",']</td><td align="right" width="140">',$redate);
  75.     $result = preg_replace("/\:\s/",':</td><td>',$rekakko2);
  76.     /* 置換作業完了 */
  77.  
  78.     if (count($date) >= 2){
  79.       $datetitle = '' . reset($date) . '' . end($date) . 'のチャットログです。';
  80.     } else {
  81.       $datetitle = '' . reset($date) . 'のチャットログです。';
  82.     }
  83.  
  84.     echo '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  85.     <html>
  86.     <head>
  87.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  88.     <title>' . $ftitle . '</title>
  89.     <link rel="shortcut icon" href="../img/favicon.ico" type="image/vnd.microsoft.icon">
  90.     <style type="text/css">
  91.     <!--
  92.       body,td,th {
  93.         color: #000000;
  94.       }
  95.       body {
  96.         background-color: #FFFFFF;
  97.         margin: 10px;
  98.         font-family:;
  99.       }
  100.     -->
  101.     </style>
  102.     <body>
  103.     <h1>【' . $ftitle .'】</h1>'
  104.     . $datetitle .'<br /><hr>
  105.     <table width="99%"><tr valign="top">'
  106.     . $result
  107.     . '</td></tr></table></body></html>';
  108.   }
  109. ?>

file_get_contents()の場合
59.  /* ファイルの読み込み */
60.  $str = file_get_contents($filename);
61.  $str = mb_convert_encoding($str, "UTF-8", "Shift_JIS, EUC-JP, UTF-8");
62.  /* ファイルの読み込み終わり */


ツリー一覧

┣A01shimix>$fdata = $_POST['file']; input要素でtype属性が
┃┗A01-1reika_ciruelashimixさん、アドバイスありがとうございます。 >
┃ ┗A01-1-1shimix前のレスにも追記しましたが、サーバに保存するのに「
┃  ┗A01-1-1-1reika_ciruelashimixさん、ありがとうございます。 いろいろ試して
┃   ┗A01-1-1-1-1shimix>逆にどういうソースコードでテストして、どういう風
┃    ┗A01-1-1-1-1-1reika_ciruela勉強になります。 サーバーに設置までしていただき、
┃     ┣A01-1-1-1-1-1-1shimix>2行目と61行目のmb_internal_encoding('utf-8');を消
┃     ┗A01-1-1-1-1-1-2pannna# 解決したのでしたらいいのですが… なんか次から
┃      ┗A01-1-1-1-1-1-2-1reika_ciruelashimixさん、pannnaさん、ありがとうございます。 所
┃       ┗A01-1-1-1-1-1-2-1-1reika_ciruela忙しくて、報告が遅くなりました。すみません。 sh
┗A02magicflute2この意見は投稿者によって削除されました。

回答一覧

並び替え:

A01 参考になった
answerershimix [9月11日 17:05] (最終編集:9月11日 23:05)

>$fdata = $_POST['file'];

input要素でtype属性がfileの場合、元ファイルの名前で作成されたりはしません。マニュアルでご確認ください。

http://jp2.php.net/manual/ja/features.file-upload.post-method.php

あと今回のフォームはform要素の書き方からして怪しいです(enctype="multipart/form-data"がない)。

http://www.tagindex.com/html_tag/form/input_file.html


保存して(あとから)使う予定がないようであれば、$_FILES['file']['tmp_name']から直接読み込んでもいいかもしれません(「読み込めれば」ですが)。そういう使い方はやったことがないので未検証です(普通はmove_uploaded_file()で移動させてから使います)。


(追記)
サーバに保存する場合でも、$_FILES['file']['name'](クライアント側の元ファイル名)は使いません。日本語のファイル名をPOSTされる危険性などもありますので。tempnam()などで適当なファイル名で保存します。必要であれば元のファイル名と保存したファイル名の関連づけを別ファイルで管理します。

この意見に回答する

ツリーへ TOPへ

A01-1
replyerreika_ciruela [9月12日 00:56]

shimixさん、アドバイスありがとうございます。

> input要素でtype属性がfileの場合、元ファイルの名前で作成されたりはしません。
なるほど、ファイルを受け取ったらテンポリファイルとして保存されるため、000.tmpなどのように名前が変わるため、ローカルのファイル名を指定するとエラーが返されるということでしょうか。

> form要素にenctype="multipart/form-data"を追加し、$_FILES['file']['tmp_name']から直接読み込み
こちら(http://perltips.twinkle.cc/php/upload_xml.php)の方法を参考に試してみましたが、動作しませんでした。

また、move_uploaded_file()なのですが、マニュアルを読んでもさっぱりなのでできればまたアドバイスいただけたら嬉しいです。

52行目以降を以下のようにしてみましたが、動作しませんでした。

  1.   $ftitle = $_POST['title'];
  2.     $filename = $_FILES['file']['name'];
  3.     $temp = $_FILES['file']['tmp_name'];
  4.     $target = './data/' . $filename;
  5.     $pathinfo = pathinfo($filename);
  6.     $fname = $pathinfo['filename'];
  7.     header("Content-Disposition: attachment; filename= $fname.html");
  8.     mb_internal_encoding("UTF-8");
  9.  
  10.     if (move_uploaded_file($temp, $target)){
  11.       $fp = fopen($target,'rb');
  12.       while ($str = fread($fp)) {
  13.       $str = mb_convert_encoding($str, "UTF-8", "Shift_JIS, EUC-JP, UTF-8");
  14.     }
  15.     fclose($fp);
  16.     } else {
  17.       echo "読み込みに失敗しました。";
  18.     }

この意見に回答する

ツリーへ TOPへ

A01-1-1
replyershimix [9月12日 01:46] (最終編集:9月12日 01:53)

前のレスにも追記しましたが、サーバに保存するのに「ローカルのファイル名」を元にしてはいけません。

こちらで試した限りでは、直接
  1. $fp = fopen($_FILES['file']['tmp_name'], 'r') or die('cannot open ' . $_FILES['file']['tmp_name']);
でも(念のためor dieは書いてますが)問題なく開けます。

#変換部分はさっぱり(何をどうしたいのか)わからないので未検証ですが(汗



>動作しませんでした。

どう、「動作しなかった」のでしょう。move_uploaded_fileに失敗するのなら$targetなどの内容を表示してみるとか、デバッグしてみることは多々あると思います。


(追記)
9/12,13はネット環境がないのでレスできません。あしからず・・

この意見に回答する

ツリーへ TOPへ

A01-1-1-1
replyerreika_ciruela [9月12日 01:58] (最終編集:9月12日 03:04)

shimixさん、ありがとうございます。
いろいろ試してみます。

(追記)
> どう、「動作しなかった」のでしょう。
今まではフォームのボタンをクリックすると、「[ファイルのダウンロード] ダイアログ 」が出てきたのですが、$_FILES['file']['tmp_name']を利用すると、フォームのボタンをクリックしても何も起こりません。

move_uploaded_fileに失敗するのなら$targetなどの内容を表示してみるとか、デバッグしてみることは多々あると思います。
恥かしいのですが、自分はEclipse PDTでテストしていますが、デバック方法がわかりません。
echo $target;はダメみたいですね・・・。
とりあえず、自分でいろいろ試してみます。

> こちらで試した限りでは、直接でも(念のためor dieは書いてますが)問題なく開けます。
フォームと$fp = fopen($_FILES['file']['tmp_name'], 'r')だけではないと思うのですが、
逆にどういうソースコードでテストして、どういう風に開けたのでしょうか?

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1 満足
replyershimix [9月12日 03:48] (最終編集:9月12日 04:07)

>逆にどういうソースコードでテストして、どういう風に開けたのでしょうか? 

とりあえず検証のための「表示」しか組み込んでいませんが、下記のソースで動作しています。fopenfileの2通りで読み込めることを確認しています。

#変換部分の検証がさっぱりわからないのでheader(content-typeの書き出し)も省きました

本当はファイルが未指定でないかとかファイルサイズが0でないかとかチェックするものは多いのですが、今回は手抜きしてます(汗
  1. <?php
  2. mb_internal_encoding('utf-8');
  3. if (!$_POST){
  4. /* フォーム出力 */
  5.   header('Content-type: text/html charset=utf-8');
  6. ?>
  7. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  8. <html>
  9. <head>
  10. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  11. <title>チャットログ(Skype)変換ツール</title>
  12. <style type=text/css>
  13. <!--
  14.   body {
  15.     background: #fffff;
  16.     font-size: 90%;
  17.     font-family:;
  18.   }
  19.   td.info {
  20.     font-size: 12px;
  21.   }
  22.   h1 {
  23.     font-size: 120%;
  24.     text-align: center;
  25.   }
  26. -->
  27. </style>
  28. </head>
  29.     <body>
  30.   <h1>txt→html<br />チャットログ(Skype)変換ツール</h1>
  31.   <form enctype="multipart/form-data" action=convert.php method=POST >
  32.    <table width=100% cellspacing=12>
  33.     <tr align=center>
  34.      <td>
  35.       <table border=0 width=480>
  36.          <tr align=left>
  37.          <td>タイトル:</td>
  38.          <td><input type="text" name="title"></td>
  39.          <td class=info>※チャットのテーマタイトルをどうぞ。<br />&nbsp;&nbsp;&nbsp;</td>
  40.        </tr>
  41.        <tr align=left>
  42.          <td>ファイル:</td>
  43.          <td><input type="file" name="file"></td>
  44.          <td class=info>※htmlファイルに変換したい<br />&nbsp;&nbsp;&nbsp;txtファイルを選択してください。</td>
  45.        </tr>
  46.       </table>
  47.      </td>
  48.     </tr>
  49.     <tr align="center">
  50.     <td><input type=submit value=変換  /></td>
  51.     </tr>
  52.     </table>
  53.   </form>
  54.   </body>
  55. </html>
  56. <?php
  57.     } else {
  58. /* POSTされたファイル内容を出力 */
  59.  
  60.     /* デバッグ用 */
  61.     header('Content-type: text/html charset=utf-8');
  62.     var_dump($_POST);
  63.     print "<hr>" . PHP_EOL;
  64.     var_dump($_FILES);
  65.     print "<hr>" . PHP_EOL;
  66.  
  67.     /* ファイルの読み込み 1 */
  68.     $array = file($_FILES['file']['tmp_name']);
  69.     foreach($array as $line) {
  70.         print mb_convert_encoding(trim($line)'utf-8''Shift_JIS, EUC-JP, UTF-8') . '<br>' . PHP_EOL;
  71.     }
  72.     print "<hr>" . PHP_EOL;
  73.  
  74.     /* ファイルの読み込み 2 */
  75.     $fp = fopen($_FILES['file']['tmp_name']'r') or die('cannnot open ' . $_FILES['file']['tmp_name']);
  76.     $str = '';
  77.     while (!feof($fp)) {
  78.        $str .= fread($fp4096) or die('read error');
  79.     }
  80.     fclose($fp);
  81.     print mb_convert_encoding(nl2br($str)'utf-8''Shift_JIS, EUC-JP, UTF-8')  . PHP_EOL;
  82.   }
  83. ?>
期間限定です(そのうち削除します)が、下記に置いています。

http://forum.lolipop.jp/test/convert.php
http://forum.lolipop.jp/test/convert.txt


(追記)
デバッグしにくい要因のひとつに下記のheader出力のタイミングがあると思います。
  1. header("Content-Disposition: attachment; filename= $fname.html");
早い段階でこれをやってしまうと、このあとのエラーメッセージが全部(画面に表示されずに)ファイルとしてブラウザに返ってしまいます。全部データを読んで変換して、出力を開始する直前に入れるべきです。そうすれば読み取り・変換では(fopenに書いているように)「or die」で止めることが出来ます。fopenがエラーになるような場合にdieで止めないとfeoffreadも延々とエラーを吐き続けます(当然freadなども本来はエラーチェックすべきです)。

#実際の運用だともう少し凝ったエラー処理をしますが、とりあえずはor dieででも止めましょう。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1
replyerreika_ciruela [9月12日 05:43] (最終編集:9月12日 06:13)

勉強になります。
サーバーに設置までしていただき、ありがとうございます。

早速、ソースをそのまま使って実行テストしてみたのですが、
フォーム自体表示されず、「0% / localhost - convert.php 完了しました」というダイアログと「ダウンロード」ダイアログが出てきます。

「ダウンロード」ダイアログ
名前: convert.php
種類: php_auto_file, 1.04KB
発信元:localhost

開いて見ると、phpソースを除いたhtmlソースのみのconvert.phpが表示されます。

2行目のmb_internal_encoding('utf-8');を消すと、
フォームが表示されましたが、txtファイルを選んだにも関わらず、これまたconvert.phpのダウンロードが始まってしまいます。

2行目と61行目のmb_internal_encoding('utf-8');を消すと、
設置していただいたものと同じ動作をしました。

環境によって左右されるものなのでしょうか?
関係あるかわからないのですが、以下が私の環境です。

Apache 2.2.14 (IPV6 enabled)
PHP 5.3.1
Eclipse 3.6.0 Helios Windows 32bit ベース / Pleiades All in One 3.6.0.20100623

(追記)
Eclipse PDTの内部ブラウザで実行してたのですが、Firefoxなどで試したところちゃんと動作しました。
Eclipse PDTの内部ブラウザが上手く動作しなかったようです(汗
お騒がせしました。

しかしながら、置換作業のある本番のconvert.phpはFirefoxでも(フォームのボタンクリック後)何も起こりません・・・。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-1
replyershimix [9月12日 07:06]

>2行目と61行目のmb_internal_encoding('utf-8');を消すと、

一瞬、mb_internal_encodingを2回書いたかと思って焦りました・・

>しかしながら、置換作業のある本番のconvert.phpはFirefoxでも(フォームのボタンクリック後)
>何も起こりません・・・。 

例示したソースで「デバッグ用」の部分を消して、読み込みをどちらか一方にして($arrayもしくは$strに格納)、置換→出力の流れでいいだろうと思います。とりあえず例示したソースでPOSTされたファイルを「そのまま」ダウンロードさせるように書き直してみてください(これが出来ないと変換以前の問題なので)。

#ひとつひとつ片付けていかないと・・
#ということで、私はここまでです。出かけます(汗

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-2
replyerpannna [9月15日 03:02] (最終編集:9月15日 03:06)

# 解決したのでしたらいいのですが…

なんか次から次へとエラーが増えているので、まずは問題点を整理しましょう。
やりたいことは大体以下のような流れになるはずです。

(1)アップロードしたいファイルを選択する
(2)サーバにファイルをアップロード
(3)サーバにアップロードしたファイルを開いて読み込み
(4)読み込んだデータを解析、変換
(5)変換した結果をファイルに書き込む(?)or画面に出力

やりたいことはこの流れでいいと思いますが、現在詰まっているのは(2)でしょうか?
それとも(3)ですか?

$_FILES変数をprint_rなりvar_dumpなりで表示してみれば、
ファイルがアップロードされていない(htmlの記述ミスが原因の可能性大)のか、
読み込む際のアップロードされているファイルのパス及びファイル名が違うのか
はっきり分かるかと思います。

また、move_upload_file関数がよく分からないとのことですが、
こちらのURLを読んでみて下さい。というかこれを見ればアップロードはきちんと
動くはずです。

http://jp2.php.net/manual/ja/features.file-upload.post-method.php

# eclipseなどの統合開発環境の内部ブラウザはエミュレートしているだけなので、
# きちんとブラウザで確認することをお勧めします。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-2-1
replyerreika_ciruela [9月16日 03:46]

shimixさん、pannnaさん、ありがとうございます。
所用でPCから離れていまして、返事が遅くなりました。すみません。

おしゃるっとり、ひとつずつ確かめていきますね。
問題点がわかったり、また問題がでましたら報告します。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-2-1-1
replyerreika_ciruela [9月23日 04:59]

忙しくて、報告が遅くなりました。すみません。

shimixさんのソースから自分のソースを付け足したら、すんなりできました。
原因はわかりませんでしたが、おかげで完成しました。
数日に渡り、ご指導ありがとうございました!

この意見に回答する

ツリーへ TOPへ

A02
answerermagicflute2 [9月12日 13:42] (最終編集:9月12日 13:46)

この意見は投稿者によって削除されました。

ツリーへ TOPへ

<<質問一覧へ



Pick Up Q&A

Q
動的なURLを静的に見せる方法
 このエントリーをはてなブックマークに追加 
A
普通に考えて、mod_rewrite でしょうね。 http://www.nishishi.com/blog/2006/01/mod_rewrite_url.html...

>>続きを読む

GETのままでは検索エンジンのロボットが拾ってくれなかったためにSEO対策として有効だと言われていますね。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)