iT邦幫忙

2022 iThome 鐵人賽

0
Modern Web

從新開始學習p5.js畫出一片天系列 第 34

D34_資料記錄與儲存的操作

  • 分享至 

  • xImage
  •  

資料記錄與儲存的操作

今天來整理有關資料記錄與儲存的操作
在網頁中有時需要記錄操作的資訊,民眾的輸入,查詢的資料等等,
在p5.js中有提供一些有關儲存等功能,
save(),saveJSON(),saveStrings(),saveTable()
但是這些指令會引發儲存的對話框,主要是要讓使用者將資料存在使用者的電腦中。

現在的需求是要在背景中儲存檔案,一般有2種方式,
一種是利用session或是cookie,另一種是利用PHP儲存檔案。
先來看看PHP的方法

p5.js提供一個記錄的功能 createWriter()
writer.print(mouseX+","+mouseY); //-- 將滑鼠座標存到writer中,並且是一筆一筆儲存
查看writer中的內容 writer.content
建立的物件是 PrintWriter

PrintWriter物件

上傳資料存成txt文字檔

JS

let writer;
let fname;
function setup() {
	writer = createWriter();
	fname = "word3.txt";
}

function draw(){
  if(mouseIsPressed){
	writer.print(mouseX+","+mouseY); //-- 將滑鼠座標寫入writer中
  }
}

function keyPressed(){
  console.log(writer);
  console.log(writer.content);
  saveTxt(writer.content.trim()); //-- 將資料傳送到PHP網頁
}

function saveTxt(txt){
	let url = "upload_txt.php";
	const xhttp = new XMLHttpRequest();
	xhttp.onload = function() {
		console.log(this.responseText);
		console.log(this.getAllResponseHeaders());
	}
	xhttp.open("POST", url);
	xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xhttp.send("fname="+fname+"&wordx="+txt);
}

writer = createWriter(); 建立writer物件
writer.print(mouseX+","+mouseY); 將資料寫入writer
writer.content.trim() 讀取writer中的內容,並去除多餘的空白字元
使用 XMLHttpRequest() 將資料上傳到 upload_txt.php

PHP (upload_txt.php)

<?php

  $wordx = $_POST["wordx"];
  $fname = $_POST["fname"];
  echo "from php: " . $wordx . "\n";

  if(strlen($wordx)>0){

    if(!file_exists($fname) || filesize($fname)==0){
        //-- 如果檔案不存在或是檔案大小為0,則直接寫入檔案
        $myfile = fopen($fname, "w") or die("Unable to open file!");
        fwrite($myfile, $wordx);
        fclose($myfile);
    } else {
        //-- 如果檔案已存在,則先將檔案讀出,加上新上傳的資料,再寫入檔案
        $myfile = fopen($fname, "r") or die("Unable to open file!");
        $txt = fread($myfile, filesize($fname));
        $txt = $txt . "\n" . $wordx;
        fclose($myfile);

        $myfile = fopen($fname, "w") or die("Unable to open file!");
        fwrite($myfile, $txt);
        fclose($myfile);

        //echo $txt;
    }
  }

?>

上傳資料存成csv表格檔

利用之前文章的範例,將網路讀取的資料儲存成csv檔
JS

let writer;
let fname;
function setup() {
	writer = createWriter();
	fname = "park_place.csv";

	let url = "https://tcgbusfs.blob.core.windows.net/blobtcmsv/TCMSV_alldesc.json";
	const xhttp = new XMLHttpRequest();
	xhttp.onload = function() {
		console.log(this);
		const json_obj = JSON.parse(this.responseText);
		console.log(json_obj.data.park);
		console.log(this.getAllResponseHeaders());

		let data1 = json_obj.data.park.filter( (x, i) => i<50 );
		console.log(data1);
		for(let x of data1){
			writer.print(x.id+","+x.area+","+x.name);
		}
	}
	xhttp.open("GET", url, true);
	xhttp.send();
}

function keyPressed(){
  console.log(writer);
  console.log(writer.content);
  saveTxt(writer.content.trim());
}

function saveTxt(txt){
	let url = "upload_csv.php";
	const xhttp = new XMLHttpRequest();
	xhttp.onload = function() {
		console.log(this.responseText);
		console.log(this.getAllResponseHeaders());
	}
	xhttp.open("POST", url);
	xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xhttp.send("fname="+fname+"&wordx="+txt+"&start=\uFEFF");
}

其中

json_obj.data.park.filter( (x, i) => i<50 ); //-- 挑選前50筆資料

在傳送資料中多傳送了一個特別的字元 '\uFEFF'
xhttp.send("fname="+fname+"&wordx="+txt+"&start=\uFEFF");
主要是在儲存成csv檔時,若用Excel開啟時,會產生亂碼的狀況,
因此若在檔案開頭加上 '\uFEFF' 就不會有亂碼了。
不過只要在檔案開頭加一次就好了,
因此,特別分開上傳這個字元,要交由PHP判斷如果是新建立檔案,再在檔案開頭加上 '\uFEFF'

PHP (upload_csv.php)

<?php

  $wordx = $_POST["wordx"];
  $fname = $_POST["fname"];
  $start = $_POST["start"];  //--  當作csv檔案開頭字元
  echo "from php: " . $wordx . "\n";

  if(strlen($wordx)>0){

    if(!file_exists($fname) || filesize($fname)==0){
        $myfile = fopen($fname, "w") or die("Unable to open file!");
        $wordx = $start.$wordx;  //-- 如果是新建立檔案,就在檔案開頭加上 '\uFEFF'
        fwrite($myfile, $wordx);
        fclose($myfile);
    } else {
        $myfile = fopen($fname, "a") or die("Unable to open file!");
        fwrite($myfile, "\n".$wordx);
        fclose($myfile);
    }
  }

?>

其中
fopen($fname, "a") : "a"的參數是指直接加在檔案的結尾,不過加入前要先加上一個換行符號 "\n"
fopen($fname, "r") : "r"的參數是指讀取檔案內容
fopen($fname, "w") : "w"的參數是指重新寫入檔案中,因此如果原本檔案有資料的話會被清除掉

上傳資料存成JSON檔

JS

let writer;
let fname;
function setup() {
	writer = createWriter();
	fname = "park_place.json";

	let url = "https://tcgbusfs.blob.core.windows.net/blobtcmsv/TCMSV_alldesc.json";
	const xhttp = new XMLHttpRequest();
	xhttp.onload = function() {
		console.log(this);
		const json_obj = JSON.parse(this.responseText);
		console.log(json_obj.data.park);
		console.log(this.getAllResponseHeaders());
        
		let data1 = json_obj.data.park.filter( (x, i) => i<30 );
		writer.print(JSON.stringify(data1));
	}
	xhttp.open("GET", url, true);
	xhttp.send();
}

function keyPressed(){
  console.log(writer);
  console.log(writer.content);
  saveTxt(writer.content.trim());
}

function saveTxt(txt){
	let url = "upload_json.php";
	const xhttp = new XMLHttpRequest();
	xhttp.onload = function() {
		console.log(this.responseText);
		console.log(this.getAllResponseHeaders());
	}
	xhttp.open("POST", url);
	xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xhttp.send("fname="+fname+"&wordx="+txt+"&start=\uFEFF");
}

其中

let data1 = json_obj.data.park.filter( (x, i) => i<30 );
writer.print(JSON.stringify(data1));  //-- 將json物件或陣列「字串化」再上傳到PHP

PHP (upload_json.php)

<?php
  $wordx = $_POST["wordx"];
  $fname = $_POST["fname"];
  echo "from php: " . $wordx . "\n";

  if(strlen($wordx)>0){
    $myfile = fopen($fname, "w") or die("Unable to open file!");
    fwrite($myfile, $wordx);
    fclose($myfile);
  }

?>

參考資料
PHP Filesystem Functions
https://www.w3schools.com/php/php_ref_filesystem.asp
fopen
https://www.php.net/manual/zh/function.fopen


上一篇
D33_網路通訊資料傳送的操作(WebSocket, OSC, MQTT)
下一篇
D35_網頁session與cookie的記錄與儲存的操作
系列文
從新開始學習p5.js畫出一片天40
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言