ページ 11

テキスト処理について

Posted: 2012年11月12日(月) 10:26
by ゆうたろう
下のようになっているテキストファイルから一番最後の行の
最初の数字と区切り文字の次を取得して変数に代入したいですがどうすればいいでしょうか

1<>9<>××××××××
2<>4<>××××××××
3<>8<>あああああ
4<>6<>××××××××
5<>8<>○○○○○○○○○○
↑と↑を取得したい

言語はphpです
よろしくおねがいします

Re: テキスト処理について

Posted: 2012年11月12日(月) 10:42
by softya(ソフト屋)
ここは始めてじゃないと思うのですが、フォーラムルールに従って質問してください。
http://dixq.net/board/board.html
丸投げは原則として禁止です。

1.正規表現が分かれば難問ではないです
2.数値が必ず1桁ならもっと簡単な方法があります。

Re: テキスト処理について

Posted: 2012年11月12日(月) 11:02
by ゆうたろう
<?php


// ファイルの中身を読んで文字列に格納する


function Filewrite(){
$f = 0;
$i = 0;
$filename = "something.txt";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
}

?>

$fと$iに上のような値を代入したいです。
値は10以上があります
正規表現はよくわからないのでできればそれ以外の方法でやりたいです
(でも一応書いて頂けないでしょうか)

Re: テキスト処理について

Posted: 2012年11月12日(月) 11:17
by softya(ソフト屋)
codeタグを使ってくださいね。
1.複数行あるので配列処理できるfile関数で読み込んだほうが処理しやすいです。
2.行は複数あるので$fと$iは配列として使うのですか?
3.正規表現は勉強してください。PHPで避けて通れるものではありません。
「正規表現は怖くない - PHP Note」
http://www.sound-uz.jp/php/note/regx
わからないことは質問してください。

Re: テキスト処理について

Posted: 2012年11月12日(月) 11:27
by beatle
区切り文字というのは「<」なのか「>」なのか,もしかして「<>」なのか.
どれですか?

正規表現の例を書いてみます.
5<>8<>○○○○○○○○○○から,2つの数字を取り出したい場合は

コード:

^(\d+)<>(\d+)<>.*$
とすればできると思います.

PHPだと

コード:

preg_match("/^(\d+)<>(\d+)<>.*$/","5<>8<>○○○○○○○○○○",$match);
match[0]:5<>8<>○○○○○○○○○○
match[1]:5
match[2]:8
となると思います.実験してないので動くかは分かりませんけども.

参考:PHP正規表現で文字列抽出

Re: テキスト処理について

Posted: 2012年11月12日(月) 11:38
by ゆうたろう
このテキストファイルは自動でどんどんデータを追加していく仕様にしたいので
配列をつかって中身を全部入れるとかpregmatchで検索とかはしたくありません。。。。
最初から最後の行から読み込む方法とかはないのでしょうか
1<>9<>××××××××
2<>4<>××××××××
3<>8<>あああああ
4<>6<>××××××××
5<>8<>○○○○○○○○○○
7
8
9


Re: テキスト処理について

Posted: 2012年11月12日(月) 12:01
by box
ゆうたろう さんが書きました:このテキストファイルは自動でどんどんデータを追加していく仕様にしたいので
配列をつかって中身を全部入れるとかpregmatchで検索とかはしたくありません。。。。
そういう「大事な」話は、最初の質問のときに書いておく方がいいと思います。
回答が来た後で「いや実は…」っていうのはちょっと…。

Re: テキスト処理について

Posted: 2012年11月12日(月) 12:06
by softya(ソフト屋)
>配列をつかって中身を全部入れるとかpregmatchで検索とかはしたくありません。。。。
readでも全部の行を読み込んでいるで言っていることに矛盾があります。

【疑問】
その行の追加は誰がするのですか?外部の別のプログラムでしょうか?

【提案】
fileで読み込めば配列になっているので配列要素数から最後の行が分かります。
最後の行数の数値を取り出すならpreg_matchが妥当だと思います。

Re: テキスト処理について

Posted: 2012年11月12日(月) 12:28
by ゆうたろう
データが何万件もあった場合
処理が遅れるという心配があるのですが大丈夫なんでしょうか(試してないのであれですが・・・)
行の数を取得したいだけなので
中身を全部配列に入れるのは無駄な気がするのですが・・・・

Re: テキスト処理について

Posted: 2012年11月12日(月) 12:33
by softya(ソフト屋)
ゆうたろう さんが書きました:データが何万件もあった場合
処理が遅れるという心配があるのですが大丈夫なんでしょうか(試してないのであれですが・・・)
行の数を取得したいだけなので
中身を全部配列に入れるのは無駄な気がするのですが・・・・
テキストファイルですので全部配列に入れるかどうかは別にして全部読むしか無いです。
$contents = fread($handle, filesize($filename));
でも全部読んでいる事には変わりありません。

データが何万件もあるようなものをtxtに入れることが間違いです。
sqliteなどデータベースを使ってください。

※ 最初に前提とする仕様は全て明らかにしてください。後出し条件が多すぎます。

【補足】
<>で分解して良いならexplode()関数と言う手もありますね。

Re: テキスト処理について

Posted: 2012年11月12日(月) 12:43
by ゆうたろう
今思ったんですが
行数だけ別のtxtファイルに保存すればいいかもしれませんね
>データが何万件もあるようなものをtxtに入れることが間違いです。
sqliteなどデータベースを使ってください。

よくいわれるんですがsqliteのメリットがわかりません。。。
txtファイルのほうが自由にデータを扱えると思うのですがどうなんでしょうか?

Re: テキスト処理について

Posted: 2012年11月12日(月) 12:49
by softya(ソフト屋)
ゆうたろう さんが書きました:今思ったんですが
行数だけ別のtxtファイルに保存すればいいかもしれませんね
それなら最後の行だけ保存したほうが速いです。
ゆうたろう さんが書きました: >データが何万件もあるようなものをtxtに入れることが間違いです。
>sqliteなどデータベースを使ってください。

よくいわれるんですがsqliteのメリットがわかりません。。。
txtファイルのほうが自由にデータを扱えると思うのですがどうなんでしょうか?
そもそも検索速度が違います。
テキストは頭からの連続的な処理に向いています。
データベースは任意の順番の処理に向いていて検索に秀でています。
最後の行だとけ取り出す処理しかしないならテキストだけの方が早いですが他の処理もするんですよね?
あと排他処理をシステムがしてくれるメリットがありますね。テキストだと自分でしないといけないです。

Re: テキスト処理について

Posted: 2012年11月12日(月) 12:53
by beatle
テキストファイルって,単なる文字の並びであって,行単位で構造化されているわけではないんですよ.
だから,もし行数が事前に分かってたとしても,最後の行を取り出すにはテキストファイルの先頭から1文字ずつ読み,改行文字かどうかを調べる必要があるんです.
ファイルの中身を配列に入れるかどうかは別ですけども,ファイルの先頭から調べる必要はあります.

もし,「最後の行の行数」ではなく,「最後の行の開始位置(ファイル先頭からの文字数)」が分かるのなら,その位置へシークすれば,最後の行だけを効率良く読み込めますけどね.

Re: テキスト処理について

Posted: 2012年11月12日(月) 13:04
by ゆうたろう
いろいろと難しいですが
sqliteのほうが検索速度が速いんですね。
一回使ってみます
ありがとうございました

Re: テキスト処理について

Posted: 2012年11月12日(月) 13:09
by softya(ソフト屋)
ゆうたろう さんが書きました:いろいろと難しいですが
sqliteのほうが検索速度が速いんですね。
一回使ってみます
ありがとうございました
検索というのはキーワードを設定して検索インデックスを使った場合だけです。
何も考えずにデータベース化するぐらいならテキストのほうが速いです。
ただ、同時動作しているPHPがあるならデータベースには排他処理のメリットはあります。
※ テキストを書き換えている間は読み込み出来ませんから。

何というか仕様が漠然としているので曖昧なアドバイスしか出来ません。

【補足】
仕様を整理できないと最適なプログラムを作ることはできません。
それなりの仕様なら、それなりの速度で動くプログラムが出来上がります。
一番肝心なのは、明確な要件定義です。

Re: テキスト処理について

Posted: 2012年11月12日(月) 13:12
by needsueda
まず行うべきことは対象のファイルを16進数ダンプすることを
お勧めします。対象のファイルがどのようにデータを保存しているのか
ご自分の目で確認することが第一歩です。
フリーソフト等でそうしたものがあればそれを利用するか、
見当たらない場合はDOSプロンプトからDebugを使えば良いと思います。
debug 対象ファイル名とすれば起動し、
[D]を押せばダンプを数行づつダンプされます。
終了する場合は[Q]を押します。

 さて、ファイルにはテキストファイルとバイナリーファイルが
ありますが、テキストファイルの1行の最終は
0x0dと0x0aであることはダンプしてみると判ります。
私なら次のように行います。
0.事前に取り込む文字列を257バイト分用意して置きます。
  257バイト全てに0x00をセットしておきます。 
1.ファイルを開きます。
2.ファイルサイズを取得します。(後で使うためです)
3.ファイルエンドまで1バイトづつ読み込みます。
4.0x0dか0x0aどうかをチェック、
  NOなら順次、文字列に取り込みます。
  0x0dなら次が0x0aであるかどうかを確認します。
  0x0dで次が0x0aなら行末と判断します。
5.これで1行分の文字列を切り出すことができた訳けですから
  これを元に次のステップに進むと良いわけです。
  加工後文字列257バイト分全てを0x00でセットします。
6.3に戻り繰り返します。
7.ファイルを閉じます。

phpは知りませんが、プログラム構成は同じかと思いまして。
1行は最大限256バイトと考えて、257バイトで十分かと。
読み込みだけなので、1バイトづつでも処理スピードはほとんど
変わりません。

Re: テキスト処理について

Posted: 2012年11月12日(月) 13:20
by softya(ソフト屋)
needsuedaさん残念ですが、その方法はWindowsかつDOS的過ぎます。
PHPは最終的にLinuxが多いサーバーで動き大抵文字コードはUTF-8で改行コードはLFです。
そういうことは前提にしないといけません。

>事前に取り込む文字列を257バイト分用意して置きます。  257バイト全てに0x00をセットしておきます。 

PHPに文字列配列を用意するという概念自体がありません。
c++のstd::stringと思ってもらったほうが良いです。c_str()を利用しない前提で。

【補足】
c++をご存じなかったようなので、BASICの文字列といったほうが良いかも知れません。

Re: テキスト処理について

Posted: 2012年11月12日(月) 17:06
by かずま
softya(ソフト屋) さんが書きました:テキストファイルですので全部配列に入れるかどうかは別にして全部読むしか無いです。
最後の部分だけ読めばよいのでは?

コード:

<?php
  $f = fopen("/tmp/sample.txt", "r");
  fseek($f, -1000, SEEK_END);
  $s = fread($f, 1000);
  fclose($f);
  $a = split("\n", $s);
  $n = count($a);
  if ($n >= 2) {
    preg_match("/^(\d+)<>(\d+)/", $a[$n-2], $m);
    echo "m[1]: ", $m[1], "<br/>", "m[2]: ", $m[2];
  }
?>