14歳の自分に衝撃の事実を告げてください

特定ファイルにある複数行の日本語文章を
「fgets」や「file_get_contents」などで画面に読み込む時は、
単純に「mb_convert_encoding」を使えば
良いと思ったのですが
下記のようには文法的にも使えませんでした。

--------------------------------------

<?php

$fp = fopen("sample.txt", "r");
$fp = mb_convert_encoding($fp, "UTF-8"); ←※間違い

if($fp){
flock($fp, LOCK_SH);
while(!feof($fp)){
$data = fgets($fp);
echo "$data<br>";
}
flock($fp, LOCK_UN);
}
fclose($fp);

?>

--------------------------------------

すでに書き込んである
日本語が複数行書かれたファイルから
文字化けしないようにデータを読み込んで表示するには
どのような処理をしたら良いのでしょうか?

複雑な処理はまだ理解できないので
簡単な処理方法があれば
お教えください。

よろしくお願いいたいます。

A 回答 (4件)

>> $fp = file_get_contents("sample.txt");



ちょっとこれは変数名がよくないですね。ただの文字列に対して「$fp」(FilePointer)は不適切でしょう。PHPの値の型と、fopen・fgets・file_get_contentsのマニュアルを再確認してください。

PHP Manual - 型
http://www.php.net/manual/ja/language.types.php

PHP Manual - fopen
http://www.php.net/manual/ja/function.fopen.php

PHP Manual - fgets
http://www.php.net/manual/ja/function.fgets.php

PHP Manual - file_get_contents
http://www.php.net/manual/ja/function.file-get-c …

個人的に「fgets」はほとんど出番がないと思っています。「1行ずつ」読み込んだところでPHPの場合は末端に改行コードが付いてきますし、ちょっと使いにくいと思います。ファイルを処理する関数はいろいろあるので下記を参考にどうぞ。

Qiita - [PHP] ファイルオープンモードに関するマニュアルの記述は間違っている #さまざまなファイル読み出し関数
http://qiita.com/mpyw/items/3adcec3c66e515895b08 …

preタグを使わない場合に導入するnl2br関数に関しては、HTMLとする場合は第2引数にfalseを指定すべきです。デフォルトだとXHTML仕様の「<br />」になってしまうので、HTML仕様の「<br>」と違うことに注意してください。

PHP Manual - nl2br
http://www.php.net/manual/ja/function.nl2br.php

応用的な方法として、fopen関数で開いたリソースに自動的に文字コードを変換するフィルタをつけることが出来ます。これに関してはマニュアルにも詳しくは載っていません。以下のブログエントリを参考にどうぞ。但し、こちらの方法の場合は文字コードの自動判定は使えないようです。あらかじめ変換元の文字コードを知っていなければなりません。

ぱせらんメモ - ストリームフィルタで文字コード変換してみる
http://d.hatena.ne.jp/pasela/20081224/stream_fil …

CP932(Windowsが名乗っている「Shift_JIS」は実際には「CP932」です)からUTF-8に変換する方法で、あなたが試みようとしたコードに一番近い形で書くならば以下のようになります。「rb」ではなく「r」単体で開くとWindowsであれば改行コードが全て「\r\n」、Linuxであれば「\n」に勝手に変換されるので、ここではOSがWindowsであると仮定します。

if ($fp = fopen('sample.txt', 'r')) {
 stream_filter_prepend($fp, 'convert.iconv.cp932/utf-8', STREAM_FILTER_READ);
 flock($fp, LOCK_SH);
 while (false !== $data = fgets($fp)) {
  echo rtrim($data) . "<br>\n";
 }
 flock($fp, LOCK_UN);
 fclose($fp);
}

ループ条件にfeof関数を含めるのは、ローカルファイルを開く場合は大して問題ないですがネットワークストリームの場合には不適切で汎用的な方法とは言えないので、fgets関数の返り値を調べる方が無難です。PHPのマニュアルもそういう書き方になっていますよね。また、

ehco "$data<br>"

とすると、実際にファイルを表示したときにソース上で

1行目[\r\n]
<br>2行目[\r\n]
<br>3行目[\r\n]
<br>4行目

となってしまって非常に不恰好なので、

1行目<br>[\n]
2行目<br>[\n]
3行目<br>[\n]
4行目

となるようにしました。というかこんなことするぐらいなら「1行ずつ」読む意味って全く無いですよね…file_get_contentsを使わないにしても、fopen+stream_get_contentsでいいような気が…
    • good
    • 0
この回答へのお礼

詳しい説明本当に感謝しております。
すぐには理解できるとは思っていませんが
少しずつよんで勉強してみます。

本当にありがとうございました!

お礼日時:2014/03/12 13:31

>教えていただいた方法で「fopen」では


>できないのでしょうか?

fopenが返すのはあくまでもファイルハンドルリソースです。実際にファイルから読込むのは


$data = fgets($fp);

この部分です。なのでechoしている部分を

echo mb_convert_encoding($data, 'utf-8', 'ASCII,JIS,UTF-8,CP51932,SJIS-win') . '<br>';

としてやればいいです。




なお、

><pre>を使わないと改行はされないのですが

nl2br(mb_convert_encoding(file_get_contents('sample.txt'), 'UTF-8', 'ASCII,JIS,UTF-8,CP51932,SJIS-win'))

として、改行コードを<br>に変換してやればいいです。
    • good
    • 0
この回答へのお礼

マニュアルが英語で意味があまり分からず
あまり見ていなかったのですが
やっと最近少しずつ分かり始めてきました。

ここでいうfopen関数も返り値の型が重要になるのですね。

ありがとうございました!

お礼日時:2014/03/12 13:29

>文字化けしないようにデータを読み込んで表示するには



ポイントは3つ

(1)すでにあるファイルであれば最初からキャラクターセットは
わかっているはずなので、それをズバリ指定してやればいい

(2)もしなんらかの理由でキャラクターセットのわからないデータを
読まなくてはいけない場合、サンプル数がすくなければどの
キャラクターセットなのか判断することは難しい
よくエディタでテキストファイルを自動判別開くと文字化けしているようなもの。
そういう場合は、テキストファイル内に特定のキーワードを埋め込むようにして
それを見て判断するのが妥当。
(たとえば昔よく利用された美乳やら京やらの文字を入れ込んでおくテクニック
UTF8には通用しませんが・・・)
私の利用しているエディタだと「@@」という文字を埋め込んでおくと
自動判定がより正確になります

(3)そもそも読み込み時にはきちんと読まれていて、出力時に文字化けしているだけかも。
その場合は、元の文字の文字コード、出力する文字コード、httpヘッダの文字コード
htmlであればmetaで指定する文字コードをあわせるとよいでしょう
    • good
    • 0
この回答へのお礼

これまで文字化けするということはなかったので
文字コードのことは全く気にしていなかったのですが
文字コードの大切さをここで知ることになりました。

まだまだ先は程遠いことを実感しております。
ありがとうございました。

お礼日時:2014/03/12 12:38

<pre><?=mb_convert_encoding(file_get_contents('sample.txt'), 'UTF-8', 'ASCII,JIS,UTF-8,CP51932,SJIS-win')?></pre>



とかでどうですか?mb_convert_encodingの第3引数は省略せずにこのように指定したほうが確実です。これが日本語ファイルを扱う上で最も正確に判定できる順番です。

この回答への補足

早速のご回答ありがとうございます。
教えていただいた方法で「file_get_contents」を使うと
上手く文字化けが回避できました。

$fp = file_get_contents("sample.txt");
$fpm = mb_convert_encoding($fp, "UTF-8", "ASCII,JIS,UTF-8,CP51932,SJIS-win");
echo $fpm;

<pre>を使わないと改行はされないのですが
課題として後で勉強してみます。

教えていただいた方法で「fopen」では
できないのでしょうか?

フォームで書き込んだ文字を読み込むのは
「mb_convert_encoding」などを
使わなくても文字化けはしないのですが
読み込んでくるファイルに直接書き込んだりすると
文字化けになってしまうということを
今回はじめて知りました。

補足日時:2014/03/12 12:28
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報