Bash: tableaux en fichier

Contenu du snippet

Peut etre vous etes vous deja retrouvé dans la situation ou vous devez enregistrer dans un tableaux plusieurs milliers d'entrées.
Le problème pour moi c'est posé, j'ai donc décidé de mette ce tableau dans un fichier.
Autant prévenir de suite, cette solution offre le désavantage d'etre très lent, mais d'un autre coté, elle préserve les ressources mémoire allouées a php, ce que je désirai.
De plus, j'ai prévu un switch entre gestion par fichier et gestion en mémoire, au cas ou ;)
Prérequis:
Il faut impérativement accés a une commande grep, en effet, cette classe lors de la lecture du tableau vient 'greper' le fichier pour trouver la ligne qui l'interresse.

Le concept:
En instanciant la class ArrayFile, on créé un fichier dans le répertoire temporaire de votre choix. Le stockage d'une variable dans ce tableau se fait par la methode add. Cette methode ecrit dans le fichier une ligne représentant l'index/key du tableau, et sa variable sérializée.
La lecture se fait par la methode get tout simplement.
Ex:
//note: le nom du tableau n'est pas obligatoire, mais il peut s'avérer interressant de retrouver le fichier que l'on a creer

$monBeauTableau = new ArrayFile('monTableau');
//ici pas besoin d'index, on incrémente automatiquement
$monBeauTableau->add('ma premiere valeur');

//ici on force l'index (15)
$monBeauTableau->add('ma seconde valeur avec un index définit',15);

//valeur index par une clé type string (cleTrois)
$monBeauTableau->add('ma troisième valeur avec clé','cleTrois');

Un accés directe a une valeur pourra etre possible via l'instruction 'get':
echo $monBeauTableau->get('cleTrois');
// resultat : ma troisième valeur avec clé

echo $monBeauTableau->get(15);
// resultat : 'ma seconde valeur avec un index définit'

Enfin, pour lister la totalité d'un tableau un simple foreachLine:
while(list($key,$value) = $monBeauTableau->foreachLine()){
echo "key = $key ";
print_r($value)."\n";
}

//unset du tableau
$monBeauTableau->unsetArray();

Un cas particulier:
si plusieurs add sont fait sur la meme clé, le get de cette clé renverra toutes les valeurs de cette clé.
Pour retourner, la dernière valeur, il faut utiliser la methode 'getUniq' au lieu de 'get'.

Source / Exemple :


<?
class ArrayFile{
	var $dirTmp = '/var/tmp/';
	var $handleW = null;
	var $handleO = null;
	var $index = null;
	var $separator = '##';
	
	
	/*
		permet de switcher entre le mode fichier (très lent mais peu gourmand) 
		et mémoire (rapide mais très gourmand)

  • /
var $typeOfStorage = 'file';//[file|mem] var $aData = null; /**
  • Constructor
  • $param: arrayName
  • $param: dirTmp
  • $param: typeOfStorage
    • /
function ArrayFile($arrayName='',$dirTmp='',$typeOfStorage = 'file'){ $this->typeOfStorage = $typeOfStorage; if($this->typeOfStorage == 'file'){ if(!$arrayName) $arrayName = uniqid(rand()); if($dirTmp!='' && is_dir($dirTmp)) $this->dirTmp = $dirTmp; if(!is_dir($this->dirTmp.'arrayFile')) mkdir($this->dirTmp.'arrayFile'); $this->dirTmp .='arrayFile/'; $this->arrayName = date('Ymd_his').'_'.$arrayName; if(file_exists($this->dirTmp.$this->arrayName)) $this->rmFile(); $this->handleW = fopen($this->dirTmp.$this->arrayName,'a'); $this->handleO = fopen($this->dirTmp.$this->arrayName,'r'); } } /** * *
    • /
function rmFile(){ exec("rm ".$this->dirTmp.$this->arrayName); } /**
  • Empilage de $varMixed par index
* *
    • /
function add($varMixed,$index=''){ if(!$index){ if(!$this->index) $this->index = 0; $mindex = $this->index; }else{ $mindex = $index; } if($this->typeOfStorage == 'file'){ fwrite($this->handleW,$this->separator.$mindex.$this->separator.serialize($varMixed)."\n"); }else{ $this->aData[$mindex][] = $varMixed; } if(!$index) $this->index++; } /**
  • Retourne toutes les occurences $index
*
    • /
function get($index){ if($index=='') return false; if($this->typeOfStorage == 'file'){ $result = shell_exec("grep '".$this->separator.$index.$this->separator."' ".$this->dirTmp.$this->arrayName." 2>&1"); $result = explode("\n",trim($result)); //si vide if($result[0]=='' && count($result)==1) return false; if(!is_array($result)) return false; foreach($result as $line){ $aTmp = explode($this->separator,trim($line)); $aArray[] = unserialize($aTmp[2]); } }else{ $aArray = $this->aData[$index]; } return $aArray; } /**
  • Ne retourne que le dernier élément ajouté pour index $index
*
    • /
function getUniq($index){ if($index=='') return false; $aResult = $this->get($index); if(!is_array($aResult)) return false; return array_pop($aResult); } /***
  • while(list($key,$value) = $aAlbum->foreachLine()){
echo "key = $key "; print_r($value)."\n"; } *
    • /
function foreachLine(){ if($this->typeOfStorage == 'file'){ if(!feof($this->handleO)){ $line = fgets($this->handleO, 4096); $aTmp = explode($this->separator,trim($line)); if($aTmp[1]!=''){ return array($aTmp[1],unserialize($aTmp[2])); }else{ return $this->foreachLine(); } }else{ fseek($this->handleO, 0); } }else{ list($k,$d) = each($this->aData); if($d!='') return array($k,$d); reset($this->aData); return false; } return false; } /** * *
    • /
function unsetArray(){ if($this->typeOfStorage == 'file'){ fclose($this->handleW); fclose($this->handleO); $this->rmFile(); }else{ unset($this->aData); } } } ?>

Conclusion :


Si vous n'avez pas peur de ralentir votre script, et si la mise en tableau demande beaucoup de ressource mémoire, alors voila une solution. L'autre solution consiste a allouer plus de mémoire a php via la config.

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.