Autor Zpráva
Návštěvník
Profil *
Dá se to nějak udělat, že když v adresáři očekávám velké množství souborů, abych mohl procházet soubory které začínají nějakým číslem a nemusel je procházet všechny? To dočasného adresáře zapisuji soubor s názvem ve formátu unixtimestamp_userid ... a chtěl bych zjistit, jestli v posledních 15 minutách uživatel s id userid již provedl akci, tím že zkontroluju existenci tohoto dočasného souboru. Ale samozřejmě že neznám jeho přesný název díky tomu že neznám přesný čas, jen časový limit.
juriad
Profil
Krátce: Ne.
Dlouze: Můžeš každý den/hodinu soubory ukládat do jiného adresáře pojenovaného třeba podle společného prefixu (prvních několika znaků názvu souboru). Pak stačí procházet takový adresář - neprocházíš všechny soubory.
Keeehi
Profil
Návštěvník:
Existuje funkce glob.

Pak ještě pokud máš pole souborů seřazené, můžeš ho od konce procházet jen dokud ten timestamp nebude větší než now-15 min.
juriad
Profil
Keeehi:
Ale tím řešíš problém na straně PHP. PHP bude muset oddřít všechnu práci funkcí glob, která musí projít názvy všech souborů. Řazení je ještě o logaritmus horší, nehledě na zbytečně spotřebovanou paměť.

Problém je v tom, že samotný filesystém ti poskytuje informace o souborech v adresářích v nějakém pořadí, které vůbec nemusí odpovídat pořadí vytváření souborů a už vůbec ne názvům souborů.

Jediné správné řešení skutečně řešící problém (které jej jen nepřesouvá) je již na úrovni filesystému: zajistit ukládání souborů do jiných adresářů.
Návštěvník
Profil *
Keeehi:
To co píše juriad - taky jsem si všiml, že to vlastně načítá pole se všemi soubory a to já nepotřebuju. Vlastně potřebuju odstranit staré soubory, a pak zkontrolovat jestli v těch nových není duplicitní soubor (duplicitní obsah od uživatele zpracovávajícího požadavek). Přehodil jsem to na userid_timestamp:

    IF ($handle = opendir(C::TEMP_PATH)):
      echo "Directory handle: $handle<br>";
      echo "Entries:<br>";
      $now = time();
      /** Check directory **/

      while (false !== ($entry = readdir($handle))):         
        $f = C::TEMP_PATH."/".$entry;
        $time = filemtime($f);
        if ($now-$time > 90000 ): // 15 minut staré soubory vymazat
            unlink($f);
        else:
          if ( $f[9].$f[8].$f[7]==$id[9].$id[8].$id[7] AND $f[6].$f[5].$f[4].$f[3].$f[2].$f[1].$f[0]==$id[6].$id[5].$id[4].$id[3].$id[2].$id[1].$id[0] 
              AND $entry<>$file 
              AND filesize($entry)==filesize($file) 
              AND file_get_contents($entry)==file_get_contents($file))  
        /** TOTO JE POKUS O OPAKOVANÉ ODESLÁNÍ:
         razítko dočasného souboru tohoto uživatele je 
         v časovém limitu menším než 15 minut a bylo 
         zjištěno, že soubor jiného jména se stejnou velikostí
         a stejným obsahem již existuje 
         */ $lan->printm(70);
        endif;
      endwhile;
    ENDIF;

A říkám si, že logické by bylo kdyby data v adresáři byly ukládány a indexovány podle stáří (od nejstaršího po nejmladší) a podle toho také procházeny. To by bylo vyhovující. Načtení / přeskočení názvů nesouvisejících s id tohoto uživatele se nevyhnu...


Nevím jestli v tom nejsou chyby, ale toto třeba opravit na celou cestu:
              AND filesize($f)==filesize($file) 
              AND file_get_contents($f)==file_get_contents($file))  

$file je cesta k souboru který jsem už částečně načetl. Je to soubor obsahují dočasné data. Ale pokud je tu duplicitní soubor, tak to hodí hlášku, že akci nelze provést.
Alphard
Profil
Pro porovnání souborů lze použít md5_file().
Na duplicity porovnáváte jen soubory z posledních 15 minut, to jich je opravdu tolik? Jestli ano, můžete si jejich kontrolní hashe ukládat někam mimo, klidně do databáze a mít tam index. Tím byste částečně mohl realizovat i svoji představu ukládání podle stáří. Na základě dotazu do databáze by se mazaly konkrétní soubory, nemusely by se procházet a načítat o nich údaje.
juriad
Profil
Návštěvník:
Na některých systémech ti může tento způsob selhat:
http://stackoverflow.com/questions/1676522/delete-files-while-reading-directory-with-readdir
Správně by sis měl ukládat kandidáty ke smazání a smazat je až po zavření adresáře (které ti tam mimochodem chybí).

Podmínku na řádku 13 můžeš realizovat pomocí sustringu a ne této šílené concatenace, přece nezáleží jestli název porovnáváš odpředu či odzadu.
Porovnávání obsahu vyžaduje spoustu dalších operací s filesystémem a může být poměrně pomalý, pokud je soubor velký.

Asi bych také šel cestou databáze a ukládání hashů souborů.
Jsou vůbec ty soubory potřeba, nešel by celý jejich obsah ukládat do databáze?
Návštěvník
Profil *
juriad:
id je například 0000000009. Když porovnám první tři bajty odzadu tedy 009 či 900 tak se sníží pravděpodobnost shody a tedy nemusím už dále porovnávat :-) Substr by volalo další funkci a v ní kopírovalo řetězec o délce 10 znaků. Tak myslím že moje řešení je rychlejší. Soubor obsahuje mimojiné text zprávy, takže velikost by měla být cca maximálně 1200, ale v praxy spíš krátká zpráva.

Alphard
To máte pravdu, že těch souborů tam vlastně moc nebude. Oni se ukládaj jen když uživatel odesílá zprávu se zakázanými slovy.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: