Page 1 sur 1

Problème avec File_put_contents

Posté : 10 janv. 2012, 00:46
par nisalon_caje
Bonjour bonjour,

Bonjour

J'ai un petit soucis avec la fonction file_put_contents.

Je m'explique :
Voici un code :

Code : Tout sélectionner

$data = array('a'=>rand(),'b'=>rand(),'c'=>rand()); file_put_contents($filename,json_encode($data), LOCK_EX);
Ce qui se passe, c'est que parfois (relativement rarement néanmoins), ce qui est écrit dans le fichier n'est pas correct (typiquement j'ai deux accolades fermantes, comme si le contenu précédent n'était pas effacé)
J'ai pensé à un problème d'écritures simultanées, mais le problème est que ce fichier ne peut être écrit que par cette fonction et que cette fonction ne peut être appelée deux fois en même temps. (néanmoins je peux avoir une lecture (via une fonction appelée par un autre client) et une écriture via cette fonction en simultané)

Auriez vous une idée du problème (ou de comment le résoudre ?)

Merci d'avance !

Re: Problème avec File_put_contents

Posté : 10 janv. 2012, 11:17
par Shenryu
Salut,

Si l'objet que tu encodes en json est un objet vide, tu peux avoir des accolades.
Tu peux tester ce que tu encodes en json dans ton fichier et vérifier qu'il ne s'agit pas d'un objet vide éventuellement ;)

Re: Problème avec File_put_contents

Posté : 10 janv. 2012, 12:39
par sirakawa
Question naïve:
quel est le but du paramètre LOCK_EX ?

Re: Problème avec File_put_contents

Posté : 10 janv. 2012, 12:53
par nisalon_caje
Non l'objet encode n'est vraiment pas vide, mon script est exactement de la forme de ce que j'ai écrit
et le résultat que j obtiens est par exemple :
{"a":5,"b":7,"c":12}}

et j'ai rajoute le lock ex ensuite (le bug apparaît également sans), afin d essayer de verrouiller fichier pendant son écriture mais ça ne change rien

Re: Problème avec File_put_contents

Posté : 10 janv. 2012, 23:06
par nisalon_caje
Bonjour

Je n'ai toujours pas résolu le problème

Après quelques tests, j'ai néanmoins remarqué le soucis suivant :
Voilà deux scripts php que je fais tourner en même temps :

Code : Tout sélectionner

<?php // Fichier "ecriture.php" set_time_limit(0); ignore_user_abort(true); $filename = 'test.json'; $puiss = array(); for($i=0;$i<10;$i++){ $puiss[$i]=pow(10,$i+1); } for ($i = 0; $i < 100000; $i++) { $data = array('a' => (mt_rand()%$puiss[rand()%10]), 'b' => (mt_rand()%$puiss[rand()%10]), 'c' => (mt_rand()%$puiss[rand()%10])); file_put_contents($filename, json_encode($data), LOCK_EX); } echo 'fini'; ?>

Code : Tout sélectionner

<?php // Fichier lecture.php set_time_limit(0); ignore_user_abort(true); $filename = 'test.json'; for ($i = 0; $i < 1000000; $i++) { $data = file_get_contents($filename); if (json_decode($data, true) == false) { echo 'Erreur !! - "'.$data.'"'; break; } } echo 'fini'; ?>
Donc je fais tourner les deux en même temps et le script lecture et le script lecture s'arrête quasi immédiatement, me montrant la chaine de caractère vide ...
Alors que selon moi, le LOCK_EX aurait du empêcher cela !

EDIT : je viens de récupérer l'erreur dont je parlasi ci-avant en faisant ce test : j'ai obtenu

Code : Tout sélectionner

{"a":71395911,"b":8808,"c":17}6}

Re: Problème avec File_put_contents

Posté : 11 janv. 2012, 00:25
par AB
Pourquoi utilises-tu json_encode pour sérialiser ton tableau ? serialize() ne te convient pas ?

Re: Problème avec File_put_contents

Posté : 11 janv. 2012, 00:50
par nisalon_caje
heu si, mais j'avais pris ce format car je connaissais pas la fonction serialize

mais cela n'explique pas pourquoi on a le problème :)

Re: Problème avec File_put_contents

Posté : 11 janv. 2012, 01:14
par AB
Faut utiliser des fonctions adaptées à ce que tu fais...
As-tu le même problème si tu fais :
$data = array('a'=>rand(),'b'=>rand(),'c'=>rand());

file_put_contents($filename,serialize ($data));

$tab = file_get_contents(unserialize ($filename));

echo '<pre>';
print_r($tab);
echo '</pre>';

Re: Problème avec File_put_contents

Posté : 11 janv. 2012, 01:30
par nisalon_caje
oui j'ai le même problème (plus de données qui ne veulent rien dire, mais des données vides dans le fichier lors de l'ouverture)

Mais, certes je n'écrivais peut être pas un bon format de fichier (peut être stocker le format json n'est pas correct si l'on est un puriste), mais je ne comprends tout de même pas pourquoi le fichier était mal écrit, la chaîne semblant être correctement calculée

Re: Problème avec File_put_contents

Posté : 11 janv. 2012, 02:07
par nisalon_caje
J'ai trouvé comment résoudre le bug (mais je ne l'ai pas parfaitement compris néanmoins).

file_get_contents ne respecte pas les verrous et par conséquent, peut ouvrir le fichier alors qu'il est en écriture.
si on remplace le file_get_contents par des fopen, flock fread alors le problème n'apparait plus ...

Reste à comprendre pourquoi la lecture pouvait affecter la lecture

Re: Problème avec File_put_contents

Posté : 11 janv. 2012, 03:39
par AB
...peut être stocker le format json n'est pas correct si l'on est un puriste)...
C'est surtout qu'à priori on s'en sert surtout pour faire des échanges php/javascript. A part dans ce cas je n'utilise jamais ces fonctions mais toujours serialize, unserialize. C'est pour cette raison que ton code m'étonnais un peu, je trouvais que tu prenais peut-être des "risques inutiles".
Mais bon le pb était ailleurs et merci pour le retour :)