質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

4回答

788閲覧

file( $file_name )の逆を行い、かつある行のある列の値を変える。

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2021/05/26 15:46

編集2021/05/27 07:55

php

1$f = file( $file_name )

により、テキストファイルを1行ずつ、配列$fに格納することが可能ですが、
この逆で、このようにして取り出した配列を、テキストファイルに書き出す(というか上書き)
することは、簡単にできるのでしょうか?やり方を教えて下さい。
(逆、なので、1次元が行数、2次元が列数、みたいに)

で、それができたら、そのまま保存しても意味がないわけで、
自分がやりたいのは、そのデータのある行のある列の値を変えた状態で、上書き保存をすることです。
それはいかにして行うのでしょうか?

例えば、POSTされたbという一次元の変数と、cという二重配列に対し、
二重配列のb行目の6列目の値を1増やして、上書きしたいとします、以下のように。

php

1<?php 2 3if (isset($_POST['b'])){ 4$b = $_POST['b']; 5$c = filter_input(INPUT_POST,"a",FILTER_DEFAULT,FILTER_REQUIRE_ARRAY); 6 7$file_name = "log.txt"; 8$c[$b][6]++; 9file_put_contents($file_name, $c); 10} 11 12?>

しかし、このように書いた所、cの出力結果が、
ArrayArrayArrayArrayArrayArrayArray
となってしまいました、つまり、中身が
ArrayArrayArrayArrayArrayArrayArray
のデータになってしまったのです。
部分的に編集どころか、複数行複数列あったデータが、1行の意味のないものになってしまいました、
どのように変更すれば、部分的に編集できるのでしょうか。

回答を受けて。
$cは二次元配列ですね、簡単にはここに元のテキストの全データが入っています。

で、そのデータの内、

$c[$b][6]++;このデータだけ、+1して、ここだけ直して元に戻したいわけです。
二次元配列だとArrayになる?ということですが、以上の事を簡単なコードでなすには、どのようにすれば良いのでしょう?

$cにはlog.txtを二次元配列として格納したデータを入れています。
n行m列目を、a[n][m]にしてる感じです(区切りは.)。

すいませんfile_put_contentsじゃないですね、上書きだから、これだと追記になるんでしたっけ。

php

1print_r($log1); 2 3$log2 = fopen("log.txt", "w"); 4fwrite($log2, $log1); 5fclose($log2);

これを実行すると、出力結果が
Array ( [0] => Array ( [0] => 10 [1] => 1 [2] => 1 [3] => 2 [4] => 3 [5] => 4 [6] => 5 [7] => 6 [8] => 70 [9] => 8 [10] => 9 ) [1] => Array ( [0] => 1 [1] => 1 [2] => 1 [3] => 2 [4] => 30 [5] => 4 [6] => 5 [7] => 6 [8] => 7 [9] => 9 [10] => 9 ) [2] => Array ( [0] => 1 [1] => 1 [2] => 1 [3] => 20 [4] => 3 [5] => 40 [6] => 5 [7] => 6 [8] => 7 [9] => 8 [10] => 9 ) [3] => Array ( [0] => 1 [1] => 10 [2] => 1 [3] => 2 [4] => 3 [5] => 4 [6] => 5 [7] => 60 [8] => 7 [9] => 8 [10] => 9 ) [4] => Array ( [0] => 1 [1] => 1 [2] => 10 [3] => 2 [4] => 3 [5] => 4 [6] => 50 [7] => 6 [8] => 7 [9] => 8 [10] => 9 ) )
となり、log.txtの中が初期化されてしまいます、なぜでしょう。

ちなみに、var_dumpすると、shuffleしてることから番号が乱雑になってますが、

array(5) { [0]=> array(11) { [0]=> string(2) "10" [1]=> string(1) "1" [2]=> string(1) "1" [3]=> string(1) "2" [4]=> string(1) "3" [5]=> string(1) "4" [6]=> string(1) "5" [7]=> string(1) "6" [8]=> string(2) "70" [9]=> string(1) "8" [10]=> string(3) "9 " } [1]=> array(11) { [0]=> string(1) "1" [1]=> string(2) "10" [2]=> string(1) "1" [3]=> string(1) "2" [4]=> string(1) "3" [5]=> string(1) "4" [6]=> string(1) "5" [7]=> string(2) "60" [8]=> string(1) "7" [9]=> int(9) [10]=> string(3) "9 " } [2]=> array(11) { [0]=> string(1) "1" [1]=> string(1) "1" [2]=> string(1) "1" [3]=> string(1) "2" [4]=> string(2) "30" [5]=> string(1) "4" [6]=> string(1) "5" [7]=> string(1) "6" [8]=> string(1) "7" [9]=> string(1) "8" [10]=> string(1) "9" } [3]=> array(11) { [0]=> string(1) "1" [1]=> string(1) "1" [2]=> string(1) "1" [3]=> string(2) "20" [4]=> string(1) "3" [5]=> string(2) "40" [6]=> string(1) "5" [7]=> string(1) "6" [8]=> string(1) "7" [9]=> string(1) "8" [10]=> string(3) "9 " } [4]=> array(11) { [0]=> string(1) "1" [1]=> string(1) "1" [2]=> string(2) "10" [3]=> string(1) "2" [4]=> string(1) "3" [5]=> string(1) "4" [6]=> string(2) "50" [7]=> string(1) "6" [8]=> string(1) "7" [9]=> string(1) "8" [10]=> string(3) "9 " } }

となりました。

回答を受けて、エラーが出たので確認すると、
fwrite() expects parameter 2 to be string,
とのことでした、引数2が文字型でないといけないということですが、
二重配列なんですが、どうすればいいんでしょうか・・・。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2021/05/26 21:53

既に過去に得た回答で解決可能です。 1回1回記憶がリセットされてるのですか?
itagagaki

2021/05/27 02:31

質問をコロコロ編集するのはやめてください。
K_3578

2021/05/27 03:25

この人の質問に回答、コメントする時間そのものが無駄だと思います。
Y.H.

2021/05/27 07:30

> @fwrite($log2, $log1); fwrite()の使用方法が間違っていれば丁寧にPHPがメッセージ表示してくれるのに わざわざエラーメッセージを抑止しているのはなぜでしょうか?
m.ts10806

2021/05/27 07:36

回答無視して自分の思ったようにしか書いてないからそうなるだけの話。
退会済みユーザー

退会済みユーザー

2021/05/27 07:44 編集

fwriteの仕様を読めないの? 日本語だいじょうぶ? 自分の考えたとおりに動かないのはphpが悪いとか思ってるの?
K_3578

2021/05/27 07:57

teratail向いてないんだろうからメンターでも雇ったら良いんじゃないかな。
退会済みユーザー

退会済みユーザー

2021/05/27 09:22 編集

配列はあくまで配列というデータ構造です。「文字列を要素に持つ配列」を要素に持つ配列です。勝手に文字列になんかなりません。配列データを文字列にどーにかこーにか加工しないと使えませんよ。
guest

回答4

0

ファイル名:340542.php

php

1<pre> 2<?php 3$dat = []; // データ保持用配列の初期化 4$tsv = file('340542.tsv'); // ファイルからデータを行単位の配列データとして読み込み 5 6foreach ($tsv as $line) { // 行単位のデータを順次処理 7 $line = chop($line); // 行末の改行コードを除去 8 $arr = explode("\t", $line); // データの区切り文字TABを基準に配列に分解 9 $id = $arr[0]; // id値として1つ目のデータを採用 10 $dat[$id] = $arr; // $datに格納 11} 12echo '=== 加工前 ===' . PHP_EOL; 13var_dump($dat); 14echo '=== 加工前 ===' . PHP_EOL; 15 16// 2で始まる行の4番目の数値を+1している 17$dat[2][3] = strval(intval($dat[2][3]) + 1); 18 19echo '=== 加工後 ===' . PHP_EOL; 20var_dump($dat); 21echo '=== 加工後 ===' . PHP_EOL; 22 23$fp = fopen('340542_out.tsv', 'w'); // 出力先ファイルをオープン 24foreach ($dat as $arr) { // 行単位のデータを順次処理 25 fputs($fp, implode("\t", $arr) . PHP_EOL); // 逆のこと:TABで1行分のデータを連結し、行末に改行コードを付与して、ファイルに出力 26} 27fclose($fp); // ファイルをクローズして保存 28 29?></pre>

ファイル名:340542.tsv

1 a z 2
2 b x 1
3 c c 3
4 d v 2
5 e b 2

webブラウザからphpを実行。

ファイル名:340542_out.tsv

1 a z 2
2 b x 2
3 c c 3
4 d v 2
5 e b 2

webブラウザ上の出力:

=== 加工前 ===
array(5) {
[1]=>
array(4) {
[0]=>
string(1) "1"
[1]=>
string(1) "a"
[2]=>
string(1) "z"
[3]=>
string(1) "2"
}
[2]=>
array(4) {
[0]=>
string(1) "2"
[1]=>
string(1) "b"
[2]=>
string(1) "x"
[3]=>
string(1) "1"
}
[3]=>
array(4) {
[0]=>
string(1) "3"
[1]=>
string(1) "c"
[2]=>
string(1) "c"
[3]=>
string(1) "3"
}
[4]=>
array(4) {
[0]=>
string(1) "4"
[1]=>
string(1) "d"
[2]=>
string(1) "v"
[3]=>
string(1) "2"
}
[5]=>
array(4) {
[0]=>
string(1) "5"
[1]=>
string(1) "e"
[2]=>
string(1) "b"
[3]=>
string(1) "2"
}
}
=== 加工前 ===
=== 加工後 ===
array(5) {
[1]=>
array(4) {
[0]=>
string(1) "1"
[1]=>
string(1) "a"
[2]=>
string(1) "z"
[3]=>
string(1) "2"
}
[2]=>
array(4) {
[0]=>
string(1) "2"
[1]=>
string(1) "b"
[2]=>
string(1) "x"
[3]=>
string(1) "2"
}
[3]=>
array(4) {
[0]=>
string(1) "3"
[1]=>
string(1) "c"
[2]=>
string(1) "c"
[3]=>
string(1) "3"
}
[4]=>
array(4) {
[0]=>
string(1) "4"
[1]=>
string(1) "d"
[2]=>
string(1) "v"
[3]=>
string(1) "2"
}
[5]=>
array(4) {
[0]=>
string(1) "5"
[1]=>
string(1) "e"
[2]=>
string(1) "b"
[3]=>
string(1) "2"
}
}
=== 加工後 ===

質問はありますか?
tsvっていう拡張子を使ったファイルは、データの区切りにTABコードを使ったものです。
真似して打ち込むときは、TABキーを押して入力してください。


log.txtの中が初期化されてしまいます、なぜでしょう。

配列を配列データのままfwriteにわたすと、
配列から文字列への自動変換が起こり、
次回読み込むための構造と全く違う構造で書き込んでしまい、
つまりは破壊してしまいます。

ファイルに直接配列を書き出すことはできない、と考えてください。
人間が読んで理解できるテキストファイルは文字列データなので、
配列データをどーにかこーにかして文字列データに連結しないとファイルになりません。
配列の要素と要素の区切りをどうするか、
1行分のデータと1行分のデータの区切りをどうするか、
ルールを決めて読み書きしているわけです。
それを無視してfwrite()に配列ドーンじゃ無理です。

投稿2021/05/27 00:51

編集2021/05/27 08:24
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/05/27 02:05

データはテキストなのですが、同じようにできますかね? ポイントは $dat[2][3] = strval(intval($dat[2][3]) + 1); $fp = fopen('340542_out.tsv', 'w'); foreach ($dat as $arr) { fputs($fp, implode("\t", $arr) . PHP_EOL); } ここですかね。入力して、そのまま一部変数を代入して、上書き、そんな簡単にできるんでしょうか? コードをもっと簡単にできますかね?
m.ts10806

2021/05/27 02:36

低評価理由が不明ですね。 「自分が理解できない内容だから」みたいな他人のせいにしたんじゃないかと邪推。 質問者のレベルだとお金払って家庭教師雇ってもスクール行っても理解できるようになると思えない。 人の話を聞かないから。 無償の、しかも質問サイトで理解できるようになるわけ無いじゃん… それくらい考えられんか
退会済みユーザー

退会済みユーザー

2021/05/27 02:45 編集

$dat[2][3] = strval(intval($dat[2][3]) + 1); を $dat[2][3]++; としてしまうと、その箇所のデータ型が(int)になってしまいます。 string型で扱うようにしているため、野暮ったいですが変換関数を加えています。 fputs()で1レコード単位の出力をしていますが、 改行コードをつけないとレコード単位の分離ができなくなってしまいます。 $id = $arr[0]; $dat[$id] = $arr; などとしているあたりもポイントなんですけどね、個人的には。 $dat[] の引数に、1列目データを与えることで目的の行データにすぐアクセスできるようにしてあるのですが。 こういう工夫をしないと、値を加工するときに、 また1行ずつデータをforeach()ループなどで紐解いて目的の行データを特定して列データの加工をする手間がかかります。 まぁ、自分でミニマルなテストコードをかかない人には伝わらないですよね、各所に凝らした工夫は。
退会済みユーザー

退会済みユーザー

2021/05/27 02:55

質問者さんの言う簡単にっていうのは、質問者さんが理解できるレベルに落とし込むことのように察するのですが、 このくらいの加工処理はまだまだ入門書レベルの話です。 わかってる人ならテスト完了まで10分~20分もあれば書ける話。 これが理解できないうちは、ふつうに入門書を写経して学習していたほうがいい、まだオリジナルなコードを書くのは時期尚早と断言します。
退会済みユーザー

退会済みユーザー

2021/05/27 03:14

変換箇所は元から数値ですが、変換の必要があるんでしょうか。 しかしちょっと複雑ですねこのコードについては・・・。
退会済みユーザー

退会済みユーザー

2021/05/27 03:52

strval()で戻さないと、その箇所だけデータ型が変わってしまうことで、 別の問題を生む可能性があります。 まぁ気にせずやってみるもいいですよ、こういうのは経験値次第なので。
退会済みユーザー

退会済みユーザー

2021/05/27 05:57

>だれとなく もっと簡単にできるんじゃねーかって、質問者さんがしっくりきてないようなので、いいのを思いついたら回答として理解用のサンプルコードを投稿してくださいまし。
退会済みユーザー

退会済みユーザー

2021/05/27 07:25

サンプルコード書いたのですが、うまくいきません、初期化されてしまいます。
退会済みユーザー

退会済みユーザー

2021/05/27 07:28

データ構造をvar_dump()などで観察せず、裏で誰かが上手にいい感じになることを期待している雑なコードを書いているうちは、進歩しないです。 次回読み込めるような構造で出力するために、丁寧に気を配ったコードをかかないと。
guest

0

php

1//ファイルオープン 2//$fからarray_popやらで取り出して書き込み 3//ファイルクローズ

ずっとコードだけ教えてと言うスタンスで質問してますよね。
自分で考える気ありますか?

投稿2021/05/26 15:59

tmsw

総合スコア97

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2021/05/26 21:52 編集

>自分で考える気ありますか? その手の指摘には一切耳を貸さない人なので低評価するだけ、 または通報で良いと思います。 回答しても全く理解してる様子はなく、指摘された質問は放置ですしね。 一種の荒らしです。
tmsw

2021/05/27 01:05

なるほど。 私も気にしないようにします!
guest

0

file_put_contents($file_name, $c);

$cには1次配列を指定できます、流れから見ると$cは2次配列で
書き込むとArrayになります

投稿2021/05/27 00:43

yambejp

総合スコア114883

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2021/05/27 00:45

悪いこと言わないので2~3冊演習タイプの参考書丸写しで実行してみる ところから始めたほうがよいですよ。 あまりにも知識と経験がなさすぎます。
退会済みユーザー

退会済みユーザー

2021/05/27 02:07

$cは二次元配列ですね、簡単にはここに元のテキストの全データが入っています。 で、そのデータの内、 $c[$b][6]++;このデータだけ、+1して、ここだけ直して元に戻したいわけです。 二次元配列だとArrayになる?ということですが、以上の事を簡単なコードでなすには、どのようにすれば良いのでしょう?
yambejp

2021/05/27 02:09

> $cは二次元配列ですね、簡単にはここに元のテキストの全データが入っています。 $cは"a"というpostデータを受けたもので、元テキストの全データは入っていないですよね?
退会済みユーザー

退会済みユーザー

2021/05/27 02:29

$cにはlog.txtを二次元配列として格納したデータを入れています。 n行m列目を、a[n][m]にしてる感じです(区切りは.)。 すいませんfile_put_contentsじゃないですね、上書きだから、これだと追記になるんでしたっけ。
yambejp

2021/05/27 02:37

ログをいじりたいなら全部読んで書き換えて全部書き込んでください。 もしくは固定長データにしてシークして書き換えても結構です file I/Oについての基本がわからないなら、演習に入る前に とにかく学習してください
退会済みユーザー

退会済みユーザー

2021/05/27 07:25

サンプルコード書いたのですが、うまくいきません、初期化されてしまいます。
guest

0

1次元が行数、2次元が列数

この意味がわからないですが…

$f = file( $file_name )

ここで配列$fの各要素は改行文字の付いたままの文字列なので、

PHP

1file_put_contents($file_name, $f)

で書き出せると思います。

もし、改行文字の付いていない文字列の配列を、要素ごとに改行を加えて出力したいなら、

PHP

1file_put_contents($file_name, implode(PHP_EOL, $f))

ですね。

投稿2021/05/26 16:02

itagagaki

総合スコア8402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/05/26 16:58

確認なのですが、$fって「配列」ですよね?しかも二次元の 改行コードってどこに入るんですか?
itagagaki

2021/05/27 00:11

どうしてそういう理解になるのですか?
itagagaki

2021/05/27 00:47 編集

それと、しれっと質問の内容が変わる編集をするのはやめてください。 回答との食い違いが生じます。
退会済みユーザー

退会済みユーザー

2021/05/27 02:08

file関数を使ったら配列になりません?
itagagaki

2021/05/27 02:09

行で分割した一次元の配列になります。そして各要素に改行コードは残されます。 ちゃんとリファレンスとか参照しているんですか?
退会済みユーザー

退会済みユーザー

2021/05/27 03:23

なるほど。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問