• ベストアンサー

配列データの書換え

お世話になっております。 タイトルにある「配列データの書換え」ですが、あるデータ用ファイル(data.txt)というのがあり、 2009-07-07 ○○@○○.com たけし no 2009-07-07 △△@○△.net ゆみこ no 2009-07-08 ○△@□○.org ひろし ok ※全角スペースの箇所は、タブ区切りとなっています。 と構成されているファイルを呼び出し、条件にて処理を行いたく、呼び出したデータ(data.txtのデータ)を配列にし、 for($i;$i<count($datafile);$i++){  $data = explode("\t", $datafile[$i]);   if($data[3] == "ok"){//ok,noだけではなく、他の条件も含めて条件処理を行っている    $str = "no";    $up_data[] = $data[0]."\t".$data[1]."\t".$data[2]."\t".$str;   } } とこんな感じで記述してみました。 これは、if文の中で条件が合致していたら、名前の後(data.txt)にある「no」を「ok」とし、 その書換えたデータをもとに、data.txtをも上書きしたいと考えているのですが、 この方法だと、data.txtのデータが増えて来たとき、効率が悪いように思えてなりません。 上記のような流れの処理を行い、元のファイルのデータを処理&上書きするもっと効率のよい スクリプトはどんな感じになるのでしょうか。 上手く説明できずに、また説明が不十分なところがあり恐縮ですが、アドバイスのほど頂戴出来れば幸いです、 宜しくお願いいたします。

  • PHP
  • 回答数2
  • ありがとう数4

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

  • ベストアンサー
noname#90314
noname#90314
回答No.1

データファイルを読み取っていくという点では あまり速度的に変わらないと思いますが かならず 行末データが ok, ng であるならば 正規表現で置換してしまうのもありではないかと思います。 a4_chapp 様の環境においてデータベースが許されない環境のため上記質問がでているとしたら余計なことかもしれませんが ただ懸念されていますとおりデータファイルの肥大化については 最終的にはデータベースに移行するのが最良の策に思えます。

a4_chapp
質問者

お礼

こんにちは。 ご親切なアドバイスをありがとう御座います。 また、こちらからのご挨拶が遅れてしまったことをお許し下さい。 >正規表現で置換してしまうのもありではないかと思います。 正規表現で置換ですか・・。色々なやり方があるのですね。 勉強になります。 >最終的にはデータベースに移行するのが最良の策に思えます。 やはりそうですね。今回の処理を考えている中、やはりDBの利用が望ましい事に改めて気付きました。

その他の回答 (1)

  • tk_uc
  • ベストアンサー率68% (33/48)
回答No.2

ある程度のデータ量が見込まれるなら、No.1の方のがおっしゃるようにDBを使用すべきです。 MySQLなどが使用できない環境でもSQLiteなら使えるのではないでしょうか。 テキストファイルへデータを保管する代わりにSQLiteで保管。 制限はあるもののSQL文が使えますので、非常に効率よく大量データを扱えます。

a4_chapp
質問者

お礼

こんばんは。ご親切なアドバイスをありがとうございます。 最近になってはじめてSQLiteを触りましたが、仰るようにMySQLが利用できない時など利用価値はありそうですね。 色々な理由があってファイルにデータを書き込む方式をとっているのですが、なんとかスクリプトの構成を変えたりして当初のときより、負荷の軽減ができたようです。ご親切なアドバイスをありがとうございます。

関連するQ&A

  • AWKの配列内データの処理について

    AWKを使用して入力ファイルの1行内の単語に対して条件チェックするには for( i=1 ; i<= NF i++ ){    if( $I == chek_word )       処理 } とすればできるのはわかるのですが、 一旦、配列の中に格納した文字列に対して上記の処理と同様の処理をするにはどのようにすればいいのでしょうか? 例えば data_line[$1] = $0; として配列data_lineに格納した1行そのままのデータに対して1番上の行全体にわたる単語の条件チェック をおこないたいのですが、どのようにすればいいのかよくわかりません。 どなたかご存知の方アドバイスをお願いします。

  • CSVからのデータ抽出と分岐

    はじめまして。ある事情からPHPを書くことになり、見よう見まねで やっておりますがどうにもこうにもなりません。お助けください。 あるPHPから「data.csv」を読み込み条件毎に表示を変えたいです。 <?php $ID=$_GET["say_id"]; $Data=file("data.csv"); for($i=0;$i<sizeof($Data);$i++){ $line=explode(",",$Data[$i]); if($line[2]==$ID && $line[0]=="0"){ //この時だけ出力したいです。 //さらに if($line[1]=="1"){ //この時以下の処理をしたいです。 $say_no=str_replace("1","こんにちは",$line[1]); $say_url=str_replace("こんにちは","konnichiwa",$say_no); } elseif($line[1]=="2"){ //上記でない場合以下の処理をしたいです。 $say_no=str_replace("2","おはよう",$line[1]); $shop_url=str_replace("おはよう","ohayou",$say_no); } elseif($line[1]=="3"){ //上記でない場合以下の処理をしたいです。 $say_no=str_replace("3","こんばんは",$line[1]); $say_url=str_replace("こんばんは","konnbannwa",$say_no); } else($line[1]=="4"){////上記でない場合以下の処理をしたいです。 $say_no=str_replace("4","さようなら",$line[1]); $say_url=str_replace("さようなら","sayounara",$say_no); } break; } } ?> if($line[1]=="1"){   ここで処理が止まってしまっているのか画面に何も出なくなります。 見た目もよろしくないような気がします・・。恐れ入りますがお力お貸しください。

    • ベストアンサー
    • PHP
  • 配列データの件数指定表示

    こんばんは。お世話になっております。 テキストファイルに保存してある配列データがあり、そのデータを呼び出したとき、10件なり20件なりの件数を制限してページング処理?を行いたいのですが、その配列にある各データには、タブ区切りで「OK」または「NO」というデータも格納されており、「NO」というデータのみを件数を制限して表示させたいと考えてます。(次ページなり前ページなりでページを変えて表示させたい) //$count テキストファイルに格納された配列のデータ数 //$string 配列データ $lim = 10;//件数制限 $ii=1; for($i=0; $i<$count; $i++){ $category_data = $string[$i]; $category_data = explode(' ',$category_data); if(trim($category_data[5]) == "no"){ $ii++; echo "○○\n";//ここにデータを表示 if($ii > $lim){break;} } } 以上が、実際にローカル上で記述しているスクリプトなのですが、先の説明のように、はじめの10件までは表示させることが出来ましたが、次ページに移動した際、11件目からのデータを取得する方法が思いつくことが出来ず、今日も朝からテストを繰り返している状況です。 このような場合、どのようにしたら宜しいのでしょうか? お忙しい中恐縮ですが、アドバイスなど頂戴できれば幸いです。 ※以下の質問も投函しており、解決済みとしておりませんが、今回の質問の延長線上にあるので、「解決済みになっていない」ことをお気づきの場合、ご了承願えればと思います。 http://oshiete1.goo.ne.jp/qa4281205.html

    • ベストアンサー
    • PHP
  • C++のファイルに対する配列データの読み書き

    C++で配列c[0],c[1],....の値をファイルに出力すると、 1.2 3.2 5.1 8.2 -9.1 のようになると思います(この例は配列のサイズが5)。実際は100以上の配列にします。 プログラム的にはだいたい下のようになると思っています。 std::ofstream ofs( "test.txt" ); ofs << ここで並びの出力をするはず? << std::endl; 意味は、出力ファイルの定義とストリームによる書き出し?と改行だと思います。 並びの出力ですから、ループでよいのでしょうか。プログラム作法が分からないので教えて頂きたいのですが。データの区切りは空白で、できれば書く数値のフォーマットは揃えたいですが。 次に、読み込むときはどうなるでしょうか。 std::ifstream ifs( "test.txt" ); std::string str; ifs >> str; std::cout << str << std::endl; これだと読んだデータを画面表示して終わりです。配列に読み込む方法なのですが。 よろしくお願いします。

  • データに「,」があると「"」でくくられます。

    タブ区切りのデータファイルaaa.txtがあり、これをMySQLに読み込んでdatabaseというテーブルを作成したいのです。 これを実行すると、1行目は 1 concon コンコン とデータを読んでくれるのですが、2行目のようにカンマがあると 2 "con,con" コンコン のように両端に"がつくのです。 con,conと表示させるにはどのようにすればよいのでしょうか。 aaa.txt(スペースはタブ区切り) 1 concon コンコン 2 con,con コンコン $fp = fopen("aaa.txt","r"); $cnt = 0; while (!feof($fp)) { $record[$cnt] = fgets($fp, 1024); $cnt += 1; } fclose($fp); $sql="create table database(no int not null primary key auto_increment,dat1 varchar(200),dat2 varchar(200))"; $rst=mysql_query($sql,$con); for ($i=0; $i<$cnt-1; $i++) { $str[$i] = explode("\t", $record[$i]); $sql="insert into database(no,dat1,dat2)values('".$str[$i][0]."','".$str[$i][1]."','" .$str[$i][2]."')"; (続く)

    • ベストアンサー
    • PHP
  • 配列

    数回に渡り質問させてもらってますが 構造体のメンバをポインタで宣言してるのが不評で 配列の方でも組んでみました。 #include <stdlib.h> #include <string.h> #include <ctype.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE -1 char* get(char **p_str); char *get_line(char buf[]); int comp_rtn(const void *p1, const void *p2); typedef struct { int number; char class_type[10]; char name[15]; char subject[10]; int ten; } my; my *data; void myswap(my *p, my *q); int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char *bufFormat; char *bufG; bufFormat =(char *)malloc(1000); bufG = (char *)malloc(1000); int line2 = 0; if((fp=fopen("jjj.txt","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); if((fp=fopen("jjj.txt","r"))==NULL){   printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); while(fgets(buf,1000,fp) != NULL){ bufFormat = get_line(buf); str = bufFormat; while(*str != '\0'){ bufG = get(&str); switch(field){      case 0: data[line].number = atoi(bufG); break case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; case 4: data[line].ten = atoi(bufG); break; } str++; field++; } line++; field = 0; } fclose(fp); qsort(data,line,sizeof(my),comp_rtn); for(int m = 0; m < line; m++){ printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject); printf("%d\n", data[m].ten); printf("\n"); } free(data); return 0; } void myswap(my *p, my *q) { my temp; temp = *p; *p = *q; *q = temp; } char *get(char **p_str) { int i; char *str; str = *p_str; static char bufG[1000]; for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else if(*str == '\\'){ str++; if(*str == 'c'){ bufG[i] = ','; } else if(*str == '"'){ bufG[i] = '"'; } } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; *p_str = str; return bufG; } char *get_line(char buf[]) { int in_quotation = FALSE, i = 0; char* str = buf; static char bufG[1000]; while(*str != '\0'){ if(*str=='"'){ if(in_quotation == TRUE){ str++; if(*str == '"'){ bufG[i] = '\\'; i++; bufG[i] = '"'; i++; } else{ in_quotation = FALSE; bufG[i] = *str; i++; } } else{ in_quotation = TRUE; } } else{ switch(*str){ case '\n': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'n'; i++; } else{ bufG[i] = *str; i++; } break; case ',': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'c'; i++; } else{ bufG[i] = *str; i++; } break; default: bufG[i] = *str; i++; } } str++; } bufG[i] = '\0'; return bufG; } ファイルは 1,犬,ボルト,国語,2 2,猫,山田,数学,1 3,犬,鈴木,英語,2 4,犬,居合,国語,1 5,猫,伊藤,数学,2 6,猫,斎藤,数学,1 こういう感じになりますが 不思議なことにこのファイルの文字列の所を 表 にすると バグって表示されます。 例えば 1,表,山田,数学,2とか 1,犬,ボルト,国語,2 2,猫,山田,数学,1 3,犬,鈴木,英語,2 4,犬,居合,国語,1 5,猫,伊藤,表,2 6,猫,斎藤,数学,1 とかです。 この現象は何故起きるのでしょうか? デバグした所、代入のときにはちゃんとしたものが代入されていますが 次の項目を代入したときにバグ化しているようです V開発環境はC++6.0のコンソールappです。

  • 読み込んだデータを配列へ代入する方法

    ---ここから--- 1,2 3,4 ---ここまで--- このようなファイルを読み込んでデータを配列へ格納するには, $pathname="D://data.txt"; open MYFILE, "$pathname"; @list=<MYFILE>; for($i=0;$i<2;$i++){ @dat=split(/,/,$list[$i]); print @dat; } close MYFILE; といったようなforあるいはwhileで1つの配列(上の場合だと@dat)に1行のデータを繰り返し入れていく方法しか思い浮かびません。できれば1行目のデータは@dat1という配列へ,2行目のデータは@dat2という配列へ,といったように行ごとに別々の配列へ代入させたいのですが良い方法はないでしょうか。 もしくは@dat=([1,2],[3,4])のような2次配列の形にでもできれば最高なのですが、、、

    • ベストアンサー
    • Perl
  • 配列にて格納したデータの出力

    txtファイルで取り込んだ2行にまたがっている数値・英文字・ひらがななどを1行ずつ配列として格納した後に、数値だけのtxtファイルとそれ以外のtxtファイルを別々に作成し、保存するプログラムを組みたいのですがよく分かりません。 ちなみに、使っているOSとAPはWinXP、Excel2003です。 InputData.txtの内容 A34bFg7p0 あ 1ylut890 B45LK4L え Number.txtの完成形 34701890 454 String.txtの完成形 AbFgp あ ylut BLKL え '変数の宣言 Dim myFile, myText, myList(), myList2(), str, B, C As String Dim XX As Integer Dim myFunc As Boolean Dim cnt, i As Long On Error GoTo myError myFile = Dir("InputDama.txt") 'ファイルの読み込み If myFile = "InputDama.txt" Then Open myFile For Input As #1 Do While Not EOF(1) Line Input #1, myText If myText <> "" Then If cnt = 0 Then ReDim myList(cnt), myList2(cnt) Else ReDim Preserve myList(UBound(myList) + 1), myList2(UBound(myList2) + 1) End If '数字・文字列の分類 CC = Len(myText) For XX = 1 To CC str = Mid(myText, XX, 1) If IsNumeric(str) = True Then '←数字かどうかはIsNumericで判断 B = B & str Else C = C & str End If Next myList(cnt) = B myList2(cnt) = C cnt = cnt + 1 End If Loop '書き込みファイルの作成 Open "Number.txt" For Output As #2 Open "String.txt" For Output As #3 For cnt = 0 To UBound(myList) Print #2, myList(cnt) Next cnt For cnt = 0 To UBound(myList2) Print #3, myList2(cnt) Next cnt Close #1, #2, #3 End Sub これだと、2行目に1行目で格納したデータが最後出てしまうので、それを取り除きたいのですが、効果的な方法が分かりませんので、宜しくお願いします。

  • 段落毎に配列に挿入するには?

    C++の基本的な配列でわからないことがあります。 例えば以下のような,3段落があるテキストファイルを用意しておき, -------------- //abc.txt abcde fghij klmno -------------- 用意した配列char data[3][20]へ, 上から順番にdata[0]に"abcde",data[1]に"fghij",data[2]に"klmno"を挿入したいです。 とりあえず1行だけ,以下のようなプログラムで出力表示できました。 #include <string> #include <iostream> using namespace std; int main() { char cir_data[3][20]; string filename("abc.txt"); FILE* fp = fopen( filename.c_str(), "r" ); fgets(data[0], 20, fp); cout << data[0] << endl; fclose(fp); return 0; } 結果は, -------------------- abcde -------------------- となったので,2・3番目もforループでできるかなと思ったら,良い結果が出ません。 以下は間違えているプログラムです。 int main() { char cir_data[3][20]; int i; string filename("abc.txt"); FILE* fp = fopen( filename.c_str(), "r" ); for(i=0; ; ){ fgets(cir_data[i], 20, fp); if(strlen(cir_data[i])<3) break; if(cir_data[i][0] != '/') i++; cout << cir_data[i] << endl; } fclose(fp); cout << "i = " << i << endl; return 0; } 結果は文字化けしてます。 何回ループしたか,iも出力してみましたが,なぜか6回カウントされています。 どこが誤っているのかわからず困っています。

  • 配列データをキーワード検索

    こんばんは。お世話になっております。タイトルにあるように配列内にあるデータを、キーワード検索をしたいと考えておりますが、テキストフォームに入力したキーワードが反映できずにいるため、アドバイスを頂戴したく投函させていただきました。 $string=array( "1組 男 高木義男 明るい性格 ok", "2組 女 高島幸子 根暗な性格 ok", "3組 男 飯田彰浩 前向きな性格 no", "2組 男 木下敏明 努力家 ok", "3組 女 結城聡子 心配性な性格 no", "1組 女 佐藤恵子 明るい性格 ok", ); 以上のような配列があり(各データのスペースはタブ区切りです)、テキストフォームで入力したキーワードを 最後のokとなっているのを条件に、名前の欄と性格の欄から、OR検索(*)をしたいのですが、上手く検索させることが出来ません。 *テキストフォームにてスペースでキーワードを入力したとき、OR検索としたい。 お忙しい中恐縮ですが、ご指導いただけたら幸いです。宜しくお願い致します。 以下が実際に記述している現在のソースです。 (テキストフォームにて入力されたキーワードをGETで送信しています) $key = urldecode($_GET["key"]); $key = mb_convert_encoding($key, 'EUC-JP', 'auto'); $key = mb_ereg_replace(" ", " ", $key); $arr = explode(" ",$key); foreach($arr as $keyy){ $wherearr[] = "(strstr($site_data_array[2], $keyy) OR strstr($site_data_array[3], $keyy))" ; } $wherestr = "(".implode(" OR ",$wherearr).")"; if($key != ""){ for($i=0; $i<$count; $i++){ $site_data = $string[$i]; $site_data_array = explode(" ", $site_data); if($wherestr AND trim($site_data_array[4]) == "ok"){ $search_array[] = implode("\t", $site_data_array);//この配列データを表示 } } }

    • ベストアンサー
    • PHP

専門家に質問してみよう