Entra

View Full Version : [PHP] Problema con stringa e salvataggio su file


VegetaSSJ5
07-02-2008, 13:39
Dunque ho pensato che per un sito che gestisco io avrebbe potuto essermi utile un file di servizio dove sono memorizzate alcune variabili tipo il contatore degli accessi, l'attuale id degli ordini (non abbiamo un db) ed eventualmente espanderlo con altri valori.

Il file l'ho chiamato service.txt ed è formato in questo modo [NOME_PARAMETRO]:[VALORE]COUNTER:19
IDORDER:20
Ho quindi scritto alcune funzioni per la gestione di questo file. Ho dei problemi con l'incremento dei valori. In realtà l'incremento funziona bene, però ogni volta che viene effettuata l'operazione di incremento (e quindi salvataggio del file) vengono inseriti tra le righe una serie esponenziale di "\n". Vi incollo qui sotto un file di test contenente le funzioni di incremento contatore + salvataggio del file. Basta fare copia/incolla su un file php ed è già funzionante (o non funzionante che dir si voglia :D).
La funzione saveFile l'ho presa da un post sul forum di php.net e presumo funzioni bene.

Potete cortesemente aiutarmi ad individuare e risolvere il problema? So che vi sto ammorbando con le mie strane richieste di aiuto, ma questa credo e spero che sia l'ultima, per questo periodo almeno... ;)
<?php

// FILE DI SERVIZIO
define("SERVICE_FILE_PATH", "service.txt");

//***** FUNCTIONS BEGIN

function updateServiceFile ($parameter) {
// MEMORIZZO RIGA PER RIGA IL FILE DI SERVIZIO NEL VETTORE $service
$service = file(SERVICE_FILE_PATH);
if (!$service) {
echo "ERRORE (".__FUNCTION__."): leggendo ".SERVICE_FILE_PATH;
exit();
}
// CERCO LA RIGA CONTENENTE IL PARAMETRO DA INCREMENTARE
foreach ($service as $index => $row) {
// SE TROVO IL PARAMETRO DA AGGIORNARE NELLA RIGA $row
if (stripos($row, $parameter) !== FALSE) {
//PRENDO LA POSIZIONE DEL DELIMITATORE :
if (($separator_pos = stripos($row, ":")) !== FALSE) {
// METTO NELLA VARIABILE IL VALORE DEL PARAMETRO, CIOè DAL CARATTERE SUCCESSIVO AL DELIMITATORE FINO A FINE STRINGA
$parameter_value = substr($row, $separator_pos+1);
// INCREMENTO IL VALORE
$parameter_value += 1;
// AGGIORNO LA RIGA $index SECONDO IL FORMATO parametro:valore
$service[$index] = trim($parameter.":".$parameter_value);
break;
}
else {
echo "ERRORE (".__FUNCTION__."): Non trovo il delimitatore due punti nella riga.<br>DEBUG INFO: Numero_riga => valore<br>".$index." => ".$row;
exit();
}
}
}
// SALVO NEL FILE LA STRINGA RESTITUITA DALLA IMPLODE
// LA IMPLODE RESTITUISCE UNA STRINGA UNICA PARTENDO DA UN VETTORE
// E SEPARA TUTTE LE RIGHE INTERMEDIE INTERPONENDO IL CARATTERE PASSATO COME PRIMO PARAMETRO
saveFile(SERVICE_FILE_PATH, implode("\n", $service));
}

function saveFile ($filename, $content) {
clearstatcache();
ignore_user_abort(true); ## prevent refresh from aborting file operations and hosing file
if (file_exists($filename)) {
// PASSANDO w COME SECONDO PARAMETRO IL FILE VIENE RIAZZERATO
// E IL SUO CONTENUTO SOSTITUITO COMPLETAMENTE CON QUELLO DEL PARAMETRO $CONTENT
$fh = fopen($filename, 'w');
while(1) {
if (flock($fh, LOCK_EX)) {
fwrite($fh, $content);
fflush($fh);
//ftruncate($fh, ftell($fh));
flock($fh, LOCK_UN);
break;
}
}
fclose($fh);
}
else {
echo "ERRORE (".__FUNCTION__."): il file da salvare non esiste.<br>File Name => ".$filename;
exit();
}
}

//******* FUNCTIONS END

//******* INCREMENTO DEL PARAMETRO "COUNTER"
updateServiceFile("COUNTER");

//******* INCREMENTO DEL PARAMETRO "IDORDER"
updateServiceFile("IDORDER");

?>

kk3z
07-02-2008, 17:02
La funziona "file" pur creando un array con un elemento per ogni riga non rimuove il carattere di newline (\n) dalla riga. Prova a trimmarlo:
$service = file(SERVICE_FILE_PATH);
if (!$service) {
echo "ERRORE (".__FUNCTION__."): leggendo ".SERVICE_FILE_PATH;
exit();
}
array_map("trim", $service);


Oppure, metodo più veloce, fai l'implode senza il \n:
saveFile(SERVICE_FILE_PATH, implode("", $service));

VegetaSSJ5
07-02-2008, 17:49
La funziona "file" pur creando un array con un elemento per ogni riga non rimuove il carattere di newline (\n) dalla riga. Prova a trimmarlo:
$service = file(SERVICE_FILE_PATH);
if (!$service) {
echo "ERRORE (".__FUNCTION__."): leggendo ".SERVICE_FILE_PATH;
exit();
}
array_map("trim", $service);
ho appena provato. stesso problema. cmq se ci fai caso il trim viene eseguito dopo in fase di assegnazione della stringa all'array.
Oppure, metodo più veloce, fai l'implode senza il \n:
saveFile(SERVICE_FILE_PATH, implode("", $service));
ci avevo già provato. in questo caso la prima volta che si esegue lo script il file conterrà una sola riga con entrambe le variabili (in pratica non mette il newline). dalla seconda volta che si esegue lo script invece la prima variabile scompare (ovviamente).

kk3z
07-02-2008, 17:57
ehm ho sbagliato è
$service = array_map("trim", $service);

MEMon
07-02-2008, 18:03
Elimina il trim ed aggiungi un new line(\n)

$service[$index] = $parameter.":".$parameter_value."\n";


poi fai l'implode con una stringa vuota

saveFile(SERVICE_FILE_PATH, implode("", $service));


Se posso darti un suggrimento, io fare così per incrementare i valori...

function updateServiceFile ($parameter) {
// MEMORIZZO RIGA PER RIGA IL FILE DI SERVIZIO NEL VETTORE $service
$service = file(SERVICE_FILE_PATH);
if (!$service) {
echo "ERRORE (".__FUNCTION__."): leggendo ".SERVICE_FILE_PATH;
exit();
}
// CERCO LA RIGA CONTENENTE IL PARAMETRO DA INCREMENTARE
foreach ($service as $index => $row) {
// SE TROVO IL PARAMETRO DA AGGIORNARE NELLA RIGA $row
if (stripos($row, $parameter) !== FALSE) {
preg_match("/\d+/",$row,$value);
$parameter_value=$value[0]+1;
$service[$index]=$parameter.":".$parameter_value."\n";
break;
}
}
// SALVO NEL FILE LA STRINGA RESTITUITA DALLA IMPLODE
// LA IMPLODE RESTITUISCE UNA STRINGA UNICA PARTENDO DA UN VETTORE
// E SEPARA TUTTE LE RIGHE INTERMEDIE INTERPONENDO IL CARATTERE PASSATO COME PRIMO PARAMETRO
saveFile(SERVICE_FILE_PATH, implode("", $service));
}

VegetaSSJ5
07-02-2008, 18:10
ehm ho sbagliato è
$service = array_map("trim", $service);
così funziona!!! (certo che anch'io sono abbastanza rinco da non accorgermi che mancava il $service =... ) :doh:

grazie!
Elimina il trim ed aggiungi un new line(\n)

$service[$index] = $parameter.":".$parameter_value."\n";


poi fai l'implode con una stringa vuota

saveFile(SERVICE_FILE_PATH, implode("", $service));


Se posso darti un suggrimento, io fare così per incrementare i valori...

function updateServiceFile ($parameter) {
// MEMORIZZO RIGA PER RIGA IL FILE DI SERVIZIO NEL VETTORE $service
$service = file(SERVICE_FILE_PATH);
if (!$service) {
echo "ERRORE (".__FUNCTION__."): leggendo ".SERVICE_FILE_PATH;
exit();
}
// CERCO LA RIGA CONTENENTE IL PARAMETRO DA INCREMENTARE
foreach ($service as $index => $row) {
// SE TROVO IL PARAMETRO DA AGGIORNARE NELLA RIGA $row
if (stripos($row, $parameter) !== FALSE) {
preg_match("/\d+/",$row,$value);
$parameter_value=$value[0]+1;
$service[$index]=$parameter.":".$parameter_value."\n";
break;
}
}
// SALVO NEL FILE LA STRINGA RESTITUITA DALLA IMPLODE
// LA IMPLODE RESTITUISCE UNA STRINGA UNICA PARTENDO DA UN VETTORE
// E SEPARA TUTTE LE RIGHE INTERMEDIE INTERPONENDO IL CARATTERE PASSATO COME PRIMO PARAMETRO
saveFile(SERVICE_FILE_PATH, implode("", $service));
}

MEMon stai diventando il mio mentore credo che adotterò la soluzione che hai postato (e che ovviamente funziona)... ;)

VegetaSSJ5
07-02-2008, 18:15
MEMon ho provato a togliere il newline dalla riga e metterlo nella implode. dovrebbe essere la stessa cosa, ma produce di nuovo lo stesso problema. come mai?function updateServiceFile ($parameter) {
$service = file(SERVICE_FILE_PATH);
if (!$service) {
echo "ERRORE (".__FUNCTION__."): leggendo ".SERVICE_FILE_PATH;
exit();
}
foreach ($service as $index => $row) {
if (stripos($row, $parameter) !== FALSE) {
preg_match("/\d+/", $row, $value);
$parameter_value = $value[0]+1;
$service[$index] = $parameter.":".$parameter_value;
break;
}
}
saveFile(SERVICE_FILE_PATH, implode("\n", $service));
}

MEMon
07-02-2008, 19:01
Mettiamo caso che il file è inizialmente questo:

COUNTER:0\n
IDORDER:0


Desideri incrementare COUNTER, il file a funzione ultimata sarà

COUNTER:1\n
IDORDER:0

Se ti limiti ad incrementare solo COUNTER non vedrai errori, ma...

Ora desideri incrementare IDORDER, il file diventerà

COUNTER:1\n
\n
IDORDER:1

in quanto hai riscritto solo la riga di IDORDER, quindi nella riga di COUNTER il "\n" era rimasto e con l'implode viene aggiunto un nuovo "\n".
Inoltre ora quando vai a leggere il contenuto del file verrà contata una riga in più.
D'ora in avanti per ogni riga che non sia quella che vuoi incrementare(compreso i falsi \n) verrà aggiunto un "\n".

VegetaSSJ5
07-02-2008, 19:05
grazie 1000! ;)