It appears you have not yet registered with DEVPPL. To register please click here... (it's fast, easy and free!)

Forum

Log In Sponsors
Board index Programming PHP and MySQL Forum Script-archive

PHP and CSV flat files!

Share your completed scripts.

Moderator: Malcolm

PHP and CSV flat files!

Postby Malcolm on Sat Jan 15, 2005 6:18 pm

Yesterday Phate PM'd me asking for a small script that would count the amount of times a user downloaded a music file. Now most people would respond with a mySQL solution; this is all well and good but mySQL connections and queries can be a huge hog on resources and response times. Why not just use a file to store these values?

Initially I sent him off a simple script that would create a new text file for each mp3 file that he had in the directory. After sleeping a few hours I came to the conclusion that the solution sucked :P

This is my new solution using a comma separated value (CSV) flat file database.
Code: Select all
<?php
//Initilized Vars
$file_types = array( 'mp3' , 'ogg' );   //accepted extensions
$dir = "music";            // directory
$count_csv = "counter.csv";       // flat-file database (comma separated values)
$file_count = array();          // the output

//var with the major stuff in it
$listing = array_output(csv_extract(), dir_read($file_types));

//Functions
function csv_extract($csv = "counter.csv")
{
   $return = array();
   if(!is_file($csv)){
      touch($csv);
   }
   $fh = fopen($csv, "r");
   while (!feof($fh)) {
      $output = explode(",", fgets($fh, 4096));
      if($output[0] !== "" && $output[1] !== ""){
         $return[$output[0]] = trim($output[1]);
      }
   }
   fclose($fh);
   return $return;
}

function csv_inject($file, $input = array(), $csv = "counter.csv")
{
   $output = "";
   $cr = "\n";
   $input[$file]++;
   foreach($input as $key => $val){
      if($key !== "" && $val !== ""){
         $output .= trim($key) . "," . trim($val) . $cr;
      }
   }
   $output = preg_replace("#(.*)\n$#", "\$1", $output);
   $fh = fopen($csv, "w");
   fwrite($fh, $output);
   fclose($fh);
}

function dir_read($types = array('mp3'), $dir = "music")
{
   $return = array();
   if (is_dir($dir)) {
      if ($dh = opendir($dir)) {
         while (($file = readdir($dh)) !== false) {
            $ext = preg_replace("#(.*)\.([a-z0-9]{3})$#", "\$2", strtolower($file));
            if(array_search( $ext, $types) !== FALSE){
               $return[$file] = 0;
            }
         }
         closedir($dh);
      }
   }
   return $return;
}

function array_output($from_csv = array(), $return = array())
{
   foreach($return as $key => $val){
      $return[$key] = $from_csv[$key];
   }
   return $return;
}

//Page output
if(isset($_GET['download'])){
   if(1===1){
      echo '<meta http-equiv="Refresh" content="1;url='.$dir."/".$_GET['download'].'">';
      csv_inject($_GET['download'], $listing);
   }
}else{
   foreach($listing as $key => $val){
      echo "<a target='_blank' href='?download=".$key."'>".$key."</a> | Downloaded ".$val." times<br />";
   }
}
?>

Functions explanations will be covered in the reply posts below
Image
User avatar
Malcolm
100+ Club
 
Posts: 198
Joined: Thu Oct 07, 2004 9:53 pm
Location: Ontario, Canada

Postby Malcolm on Sat Jan 15, 2005 6:33 pm

Code: Select all
function csv_extract($csv = "counter.csv")
{
   $return = array();
   if(!is_file($csv)){
      touch($csv);
   }
   $fh = fopen($csv, "r");
   while (!feof($fh)) {
      $output = explode(",", fgets($fh, 4096));
      if($output[0] !== "" && $output[1] !== ""){
         $return[$output[0]] = trim($output[1]);
      }
   }
   fclose($fh);
   return $return;
}


This function opens the csv flat file and dumps the variables into an array. This function will only work where ther are 2 value for each entry. EG: in this script we have a filename and a number.

Code: Select all
function csv_inject($file, $input = array(), $csv = "counter.csv")
{
   $output = "";
   $cr = "\n";
   $input[$file]++;
   foreach($input as $key => $val){
      if($key !== "" && $val !== ""){
         $output .= trim($key) . "," . trim($val) . $cr;
      }
   }
   $output = preg_replace("#(.*)\n$#", "\$1", $output);
   $fh = fopen($csv, "w");
   fwrite($fh, $output);
   fclose($fh);
}

This function is called when a file is downloaded. The file currently being downloaded is $file and its count value gets incremented.
Next we go through the array, making sure we aren't writing empty array elements to the flat file.
We "trim" the white space off the values, then make a new line for the next element.
the preg_replace statement is removing the last new line from the file, then we write out the info to the file.

Code: Select all
function dir_read($types = array('mp3'), $dir = "music")
{
   $return = array();
   if (is_dir($dir)) {
      if ($dh = opendir($dir)) {
         while (($file = readdir($dh)) !== false) {
            $ext = preg_replace("#(.*)\.([a-z0-9]{3})$#", "\$2", strtolower($file));
            if(array_search( $ext, $types) !== FALSE){
               $return[$file] = 0;
            }
         }
         closedir($dh);
      }
   }
   return $return;
}

This function reads the content of a directory, gets the extension of the files (using the preg_replace statement), check to see if out extension is listed in the allowed extensions array. If the file meets our conditions its written to the directory listing array, with a value of 0 (funky but explained later).

Code: Select all
function array_output($from_csv = array(), $return = array())
{
   foreach($return as $key => $val){
      $return[$key] = $from_csv[$key];
   }
   return $return;
}

This function merges the arrays we got from the csv_extract and dir_read functions.
Basically we go through the dir list and replace its count value for the one we got from the csv file. Whats why in the dir_read function we assigned 0 to the array elements.

Code: Select all
//Page output
if(isset($_GET['download'])){
   if(1===1){
      echo '<meta http-equiv="Refresh" content="1;url='.$dir."/".$_GET['download'].'">';
      csv_inject($_GET['download'], $listing);
   }
}else{
   foreach($listing as $key => $val){
      echo "<a target='_blank' href='?download=".$key."'>".$key."</a> | Downloaded ".$val." times<br />";
   }
}

This, amazingly enough, is the output. I expect that any user would change the looks. :)

Hope this is helpful to anyone wanting a non-sql solution for a small script.
Image
User avatar
Malcolm
100+ Club
 
Posts: 198
Joined: Thu Oct 07, 2004 9:53 pm
Location: Ontario, Canada

Postby Phate on Sat Jan 15, 2005 8:27 pm

Thanks man! im on my way to test it out!

EDIT_____

Works great!

here it is in action... so far
Im still going to tweak it a little, but the code works great!

http://thefury.zbrooks.com/songs.php
Web-Developing since '03
Image
User avatar
Phate
500+ Club
 
Posts: 826
Joined: Sun Nov 21, 2004 4:12 am
Location: 127.0.0.1


Who is online

Users browsing this forum: No registered users and 0 guests