Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Multifile
Forum PHP.pl > Forum > Przedszkole
młody skryptadept
Witajcie.
Ma poczatku chcialem sie przedstawic, jestem mlodym programista php, moje dosiadczenie nie jest dluzsze niz 1 rok.
Napisalem biblioteke do obslugi plikowej bazy danych,
sam stosuje jej zamiast sqla tongue.gif
ale moze ona tez posluzyc 'normalnym' jaki jej substytut.
Np. kiedy musimy magazynowac duzo malych obrazkow.


oto przyklad uzycia bazy:
  1. <?php
  2. require_once('multifile.php');
  3. $db->debug = false;
  4. $db = new multifile;
  5. $db->dbpath = './example/';
  6. # Dokumentacja szalenie prosta, bo i prosta jest obsluga tego lib'a
  7. # Mamy do dyspozycji 5 metod:
  8.  
  9. //foreach ( glob('ZDJECIA_Z_REJSU/*') as $file) {
  10. //    $data = array($file, file_get_contents($file));
  11. //    $db->put($data);
  12. //}
  13. //exit;
  14.  
  15. # put()
  16.    $data = array('klucz', 'string'); # stringi
  17.    $data = array('klucz', array('tablica')); # tablice
  18.    $data = array('klucz', file_get_contents('zdjecie.jpg')); # dane binarne
  19.    $db->put($data);
  20.  
  21. # get()
  22.    $data = $db->get('klucz');
  23.  
  24. # delete()
  25.    $wynik = $db->delete('klucz');
  26.  
  27. # exists()
  28.    if ( true === $db->exists('klucz'));
  29.        echo 'Klucz istnieje';
  30.  
  31. # search()
  32.    $wynik = $db->search("^klucz$"); // wyrazena regularne
  33.    
  34. # get_list()
  35.    $pelna_lista_recordow = $db->get_list();
  36.  
  37. # count
  38.    $ilosc_recordow = $db->count();
  39.  
  40. ?>


A to właściwa biblioteka:

[/php]
<?php
/*
CHANGELOG
# v.1.0



*/
/*

ToDo:
# Co szybsze, array_key_exists czy issset questionmark.gif?

Functionlist:
get()
delete()
exists() // exists powinno uzywac searcha smile.gif
search()
count()
get_list()
update()
*/
class multifile {
/* # TODO
dzielenie duuuzych plikow na porcje
szukanie od najstarszego, od najmlodszego, losowo
*/
var $dbpath = '';
var $debug = false;

var $_update = '';


function update($key, $data) {
$this->_update = $data;
if ( true === $this->_seek($key, 'update'))
return true;
return false;
}

function put($enter) {
$time_start = $this->gmt();
$key = @current($enter) or die('Zapisywac mozna tylko tablice');
$enter = array_slice($enter, 1);
if ( true !== $this->exists($key))
return false;
$path = $this->_get_writable_file();
$data = @file_get_contents($path) or die('Can\'t read from file file.');
$data = unserialize($data);
$data[$key] = $enter;
file_put_contents($path, serialize($data));
if ( $this->debug !== false ) echo 'Czas wstawiania: '.($this->gmt() - $time_start).'<br />';
return true;
}

function _is_dir($path='') {
$path = empty($path) ? $this->dbpath : $path;
if ( ! is_dir($path))
@mkdir($path, '0777') or die('Blad odczytu/zapisu bazy danych.<br />');
return true;
}

function get($key, $how='') {
/* Zrobic random
$how =
'random'
'back'
*/
$time_start = $this->gmt();
$this->_is_dir();
$key = is_array($key) ? current($key) : $key;
if ( false !== $data = $this->_seek($key, 'get')) {
//$data = unserialize($data); ###
if ( $this->debug !== false ) echo 'Czas wyciagania: '.($this->gmt() - $time_start).'<br />';
return ( count($data) < 2 ) ? $data[0] : $data; // jesli tablica ma 1 element, to zwraca tylko string smile.gif
}
if ( $this->debug !== false ) echo 'Czas wyciagania - nieudany-: '.($this->gmt() - $time_start).'<br />';
return false;
}

function exists($key) {
$time_start = $this->gmt();
$this->_is_dir();
if ( true === $this->_seek($key, 'exists'))
return false;
return true;
}

function delete($key='') {
$time_start = $this->gmt();
$this->_is_dir();
if ( true === $this->_seek($key, 'delete'))
return true;
return false;
}

function count() {
$time_start = $this->gmt();
$this->_is_dir();
return; $this->_seek('', 'count');
}

function get_list($pattent='') {
$time_start = $this->gmt();
$this->_is_dir();
$list = $this->_seek('', 'list');
if ( $this->debug !== false ) echo 'Czas generowania listy: '.($this->gmt() - $time_start).'<br />';
return $list;
}

function search($pat='') {
$time_start = $this->gmt();
$finded = array();
foreach ( $this->_seek('', 'list') as $key ) {
if ( preg_match("#$pat#", $key))
array_push($finded, $key);
}
if ( $this->debug !== false ) echo 'Czas szukania: '.($this->gmt() - $time_start).'<br />';
return $finded;
}

function _seek($key='', $do) {
switch($do) {
case('count'):
$count = 0;
break;
case('list'):
$list = array();
break;
default:
if ( strlen($key) < 1)
return false;
}
foreach ( $this->_get_files_list() as $file ) {
$db_data = @file_get_contents($file) or die('Cam\'t read db file.');
$db_data = unserialize($db_data);
if ( $do == 'count') {
$coun += count($db_data);
continue;
}
if ( $do == 'list' ) {
$list = array_merge( $list, array_keys($db_data) );
continue;
}
if ( ! array_key_exists($key, $db_data))
continue;
switch($do) {
case('get'):
return $db_data[$key];
case('update'):
$db_data[$key] = $this->_update;
file_put_contents($file, serialize($db_data));
return true;
case('delete'):
unset($db_data[$key]);
file_put_contents($file, serialize($db_data));
return true;
case('exists'):
return true;
default:
die('Blad uzycia _seek()');
}
}
switch($do) {
case('count'):
return $count;
case('list'):
return $list;
default:
return false;
}
}

function _get_files_list() {
$time_start = $this->gmt();
$this->_is_dir();
return glob($this->dbpath.'*');
}

function _get_writable_file() {
$time_start = $this->gmt();
$this->_is_dir();
$filelist = glob($this->dbpath . '*');
foreach ( $filelist as $file ) {
if ( filesize($file) < $this->_get_memory_limit())
return $file;
}
sort($filelist);
$new_file_path = is_file(end($filelist)) ? preg_replace_callback( '#^(.*?/)([0-9]+)$#', create_function('$vars', 'return $vars[1].($vars[2] + 1);'), end($filelist)) : $this->dbpath.'0';
file_put_contents($new_file_path, serialize(array())) or die('Nie moge utworzyc pliku bazy danych');
//file_put_contents(is_file(end($filelist)) ? preg_replace_callback( '#^(.*?/)([0-9]+)$#', create_function('$v', 'return $v[1].($v[2] + 1);'), end($filelist)) : $this->dbpath.'0', serialize(array())) or die('Nie moge utworzyc pliku bazy danych');
return $new_file_path;
}

function _get_memory_limit() {
$time_start = $this->gmt();
return abs(intval(ini_get('memory_limit'))) * 1024 * 1024 * 0.3;
}

function gmt(){list($usec,$sec)=explode(' ',microtime());return ((float)$usec + (float)$sec);}
}?>
[/php]

Serdecznie prosze o gro uwag.
Co Wy na to, czy z takim stylem nadaje sie na etat? smile.gif
Gość
Zle wkleila sie biboteka, oto ona jeszcze raz, tym razem z tabulatorami i bbcode:p

  1. <?php
  2.    /*
  3.         CHANGELOG
  4.         # v.1.0
  5.         
  6.     
  7.     
  8.     */
  9. /*
  10.  
  11. ToDo:
  12.     # Co szybsze, array_key_exists czy issset questionmark.gif?
  13.  
  14. Functionlist:
  15.     get()
  16.     delete()
  17.     exists() // exists powinno uzywac searcha :)
  18.     search()
  19.     count()
  20.     get_list()
  21.     update()
  22. */
  23. class multifile {
  24.    /* # TODO
  25.         dzielenie duuuzych plikow na porcje
  26.         szukanie od najstarszego, od najmlodszego, losowo
  27.     */
  28.    var $dbpath = '';
  29.    var $debug = false;
  30.    
  31.    var $_update = '';
  32.    
  33.    
  34.    function update($key, $data) {
  35.        $this->_update = $data;
  36.        if ( true === $this->_seek($key, 'update'))
  37.            return true;
  38.        return false;
  39.    }
  40.    
  41.    function put($enter) {
  42.        $time_start = $this->gmt();
  43.        $key = @current($enter) or die('Zapisywac mozna tylko tablice');
  44.        $enter = array_slice($enter, 1);
  45.        if ( true !== $this->exists($key))
  46.            return false;
  47.        $path = $this->_get_writable_file();
  48.        $data = @file_get_contents($path) or die('Can't read from file file.');
  49.        $data = unserialize($data);
  50.        $data[$key] = $enter;
  51.        file_put_contents($path, serialize($data));
  52.        if ( $this->debug !== false ) echo 'Czas wstawiania: '.($this->gmt() - $time_start).'<br />';
  53.        return true;
  54.    }
  55.    
  56.    function _is_dir($path='') {
  57.        $path = empty($path) ? $this->dbpath : $path;
  58.        if ( ! is_dir($path))
  59.            @mkdir($path, '0777') or die('Blad odczytu/zapisu bazy danych.<br />');
  60.        return true;
  61.    }
  62.    
  63.    function get($key, $how='') {
  64.        /* Zrobic random
  65.             $how =
  66.             'random'
  67.             'back'
  68.         */
  69.        $time_start = $this->gmt();
  70.        $this->_is_dir();
  71.        $key = is_array($key) ? current($key) : $key;
  72.        if ( false !== $data = $this->_seek($key, 'get')) {
  73.            //$data = unserialize($data); ###
  74.            if ( $this->debug !== false ) echo 'Czas wyciagania: '.($this->gmt() - $time_start).'<br />';
  75.            return ( count($data) < 2 ) ? $data[0] : $data; // jesli tablica ma 1 element, to zwraca tylko string :)
  76.        }
  77.        if ( $this->debug !== false ) echo 'Czas wyciagania - nieudany-: '.($this->gmt() - $time_start).'<br />';
  78.        return false;
  79.    }
  80.  
  81.    function exists($key) {
  82.        $time_start = $this->gmt();
  83.        $this->_is_dir();
  84.        if ( true === $this->_seek($key, 'exists'))
  85.            return false;
  86.        return true;
  87.    }
  88.    
  89.    function delete($key='') {
  90.        $time_start = $this->gmt();
  91.        $this->_is_dir();
  92.        if ( true === $this->_seek($key, 'delete'))
  93.            return true;
  94.        return false;
  95.    }
  96.    
  97.    function count() {
  98.        $time_start = $this->gmt();
  99.        $this->_is_dir();
  100.        return; $this->_seek('', 'count');
  101.    }
  102.    
  103.    function get_list($pattent='') {
  104.        $time_start = $this->gmt();
  105.        $this->_is_dir();
  106.        $list = $this->_seek('', 'list');
  107.        if ( $this->debug !== false ) echo 'Czas generowania listy: '.($this->gmt() - $time_start).'<br />';
  108.        return $list;
  109.    }
  110.    
  111.    function search($pat='') {
  112.        $time_start = $this->gmt();
  113.        $finded = array();
  114.        foreach ( $this->_seek('', 'list') as $key ) {
  115.            if ( preg_match("#$pat#", $key))
  116.                array_push($finded, $key);
  117.        }
  118.        if ( $this->debug !== false ) echo 'Czas szukania: '.($this->gmt() - $time_start).'<br />';
  119.        return $finded;
  120.    }
  121.    
  122.    function _seek($key='', $do) {
  123.        switch($do) {
  124.            case('count'):
  125.                $count = 0;
  126.                break;
  127.            case('list'):
  128.                $list = array();
  129.                break;
  130.            default:
  131.                if ( strlen($key) < 1)
  132.                    return false;
  133.        }
  134.        foreach ( $this->_get_files_list() as $file ) {
  135.            $db_data = @file_get_contents($file) or die('Cam't read db file.');
  136.            $db_data = unserialize($db_data);
  137.            if ( $do == 'count') {
  138.                $coun += count($db_data);
  139.                continue;
  140.            }
  141.            if ( $do == 'list' ) {
  142.                $list = array_merge( $list, array_keys($db_data) );
  143.                continue;
  144.            }
  145.            if ( ! array_key_exists($key, $db_data))
  146.                continue;
  147.            switch($do) {
  148.                case('get'):
  149.                    return $db_data[$key];
  150.                case('update'):
  151.                    $db_data[$key] = $this->_update;
  152.                    file_put_contents($file, serialize($db_data));
  153.                    return true;
  154.                case('delete'):
  155.                    unset($db_data[$key]);
  156.                    file_put_contents($file, serialize($db_data));
  157.                    return true;
  158.                case('exists'):
  159.                    return true;
  160.                default:
  161.                    die('Blad uzycia _seek()');
  162.            }
  163.        }
  164.        switch($do) {
  165.            case('count'):
  166.                return $count;
  167.            case('list'):
  168.                return $list;
  169.            default:
  170.                return false;
  171.        }
  172.    }
  173.  
  174.    function _get_files_list() {
  175.        $time_start = $this->gmt();
  176.        $this->_is_dir();
  177.        return glob($this->dbpath.'*');
  178.    }
  179.    
  180.    function _get_writable_file() {
  181.        $time_start = $this->gmt();
  182.        $this->_is_dir();
  183.        $filelist = glob($this->dbpath . '*');
  184.        foreach ( $filelist as $file ) {
  185.            if ( filesize($file) < $this->_get_memory_limit())
  186.                return $file;
  187.        }
  188.        sort($filelist);
  189.        $new_file_path = is_file(end($filelist)) ? preg_replace_callback( '#^(.*?/)([0-9]+)$#', create_function('$vars', 'return $vars[1].($vars[2] + 1);'), end($filelist)) : $this->dbpath.'0';
  190.        file_put_contents($new_file_path, serialize(array())) or die('Nie moge utworzyc pliku bazy danych');
  191.        //file_put_contents(is_file(end($filelist)) ? preg_replace_callback( '#^(.*?/)([0-9]+)$#', create_function('$v', 'return $v[1].($v[2] + 1);'), end($filelist)) : $this->dbpath.'0', serialize(array())) or die('Nie moge utworzyc pliku bazy danych');
  192.        return $new_file_path;
  193.    }
  194.    
  195.    function _get_memory_limit() {
  196.        $time_start = $this->gmt();
  197.        return abs(intval(ini_get('memory_limit'))) * 1024 * 1024 * 0.3;
  198.    }
  199.    
  200. function gmt(){list($usec,$sec)=explode(' ',microtime());return ((float)$usec + (float)$sec);}
  201. }?>
Pilsener
Operujesz na tablicach - moim zdaniem powinieneś iść bardziej w stronę while + fgets, żeby parsować pliki linijka po linijce - w ten sposób można szybko "obrabiać" nawet pliki, które mają 10MB. Swojego czasu interesowałem się plikami i napisałem nawet tutka:
http://www.forumweb.pl/viewtopic.php?t=39103
Przetestuj swój kod na jakiejś bazie, powiedzmy z 10 tysięcy rekordów - tak trudno powiedzieć, czy jest wydajny, nie ma błędów itp. Zmierz szybkość, zużycie pamięci - wrzuć demo na jakiś darmowy host.
-gox-
Taki kod jest znacznie wydajniejszy niz fgets.... znacznie, znaczenie wydajniejszy.
Dysk laduje po 100MB/s smile.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.