Autor Zpráva
pavel_pokorny
Profil
Mám problém s nahráním a výpočtem průměru ze souboru - soubor je číselný a řádek obsahuje vždy jen jedno libovolné číslo.
Jednou mi to prošlo a při načitání jiného souboru mi to vyhodilo chybu.

píše mi to:
Warning: file(text.txt): failed to open stream: No such file or directory ... on line 16
Warning: Division by zero in ... on line 27

Dále si nevím rady:
Jak zkontrolovat zda se jedná v souboru jen o čísla?
Při změně souboru se mi data neaktualizují?

Kompletní script zde:
<!DOCTYPE html>
<?php
// post file
if(isset($_POST['submit'])) {
    $file = $_FILES['file']['name']; // posted file
    
    // parsing of file type
    $parse = explode('.',$file);
    $pripona = $parse['1'];
   
   
    if(empty($file)){
        $_error = 'Chyba: Nenahráváte žádný soubor!';
    } else {
        if($pripona == 'txt' or $pripona == 'csv') {
            $fp = file($file);
            //if(preg_match('/[0-9\s]+$/', $fr)) {
            $hodnota = array(); // define value for array
            
            // make an array from file
            for($i = 0; $i < count($fp); $i++) {
                echo $hodnota[] = $fp[$i];                
            }
                                                   
            // filtering values
            $uprava = array_filter($hodnota, create_function('$hodnota','return preg_match("#\S#", $hodnota);'));
            $prumer = array_sum($hodnota)/count($uprava);
            
            /*
            } else {
                $_error = 'Chyba: Soubor neobsahuje jen čísla!';
            }
             */
        } else {
            $_error = 'Chyba: Nahráváte nepovolený formát souboru!';
        }
     }
    
}

$page  = '<html>';
$page .= '<head>';
$page .= '<meta charset="UTF-8">';
$page .= '<title>Úkol - Ing. Pavel Pokorný</title>';
$page .= '<link rel="stylesheet" type="text/css" href="css.css">';
$page .= '</head>';
$page .= '<body>';

// inputs files
$page .= '<div id="results">';
if(!empty($_error)) {
    $page .= '<span>'.$_error.'</span>';
} 
if(!empty($prumer)){
    $page .= '<b>Výsledek:</b><br> Aritmetický průměr je: <span>'.$prumer.'</span>';
}
$page .= '</div>';
$page .= '<form action="" method="post" enctype="multipart/form-data">';
$page .= '<label for="file">Zvolte soubor:</label><input type="file" name="file" value="" id="file"><em>povolené formáty souboru jsou: .txt, .csv</em><br>';
$page .= '<input type="submit" name="submit" value="odeslat">';
$page .= '</form>';
 
$page .= '</body>';
$page .= '</html>';

echo $page;

Děkuji moc za radu
Alphard
Profil
Tak si přečtěte ty chyby, co vám to píše. Zadaný soubor neexistuje, protože ho hledáte na špatném místě, správný název souboru po uploadu je v $_FILES['file']['tmp_name'].
Dělení nulou matematicky není definováno, takže si výpočet musíte ošetřit podmínkou tak, aby k němu nemohlo dojít.
pavel_pokorny
Profil
já si je právě četl, jen mi nejde do hlavy, že jeden soubor formátu .txt mi projde i s $_FILLES['file']['name'] v pohodě a spočítá se. Drůhý s podobnými čísly mi vyhazuje chybu. Dělení nulou tam být nemůže, jelikož soubory jsou nenulové.
Testoval jsem to na 'tmp_name', ale to mi nepomůže, potřebuju, aby se soubory nahrávaly jen z toho inputu.
I tak děkuji za radu.
Alphard
Profil
Asi už existuje. Neřešte případy, které fungují náhodou :-) a znovu si přečtěte, pod jakým klíčem máte hledat uploadovaný soubor.
Tori
Profil
pavel_pokorny:
Dělení nulou tam být nemůže, jelikož soubory jsou nenulové.
Soubor může obsahovat cokoliv, ale když máte špatnou cestu k souboru, tak vám file na ř.16 vrátí false, cyklus for se neprovede, v $hodnota zůstane prázdné pole, a nakonec dělíte nulu nulou.

Jak zkontrolovat zda se jedná v souboru jen o čísla?
Pouze celá čísla, bez mezer okolo: return preg_match("#^\d+$#", $hodnota);

Ale dalo by se použít i tohle: array_filter($hodnota, 'intval'); - nečíselné položky to vyháže, ale na druhou stranu tam projde exponenciální zápis čísel (1e5), záleží na vás, jestli ho chcete povolit. array_sum v podstatě všechny nečíselné položky přetypovává na čísla, 1e2 připočítá správně, takže pokud byste nepotřeboval upozorňovat na chybný formát souboru, tak tam ř.26 ani být nemusí.

K volání file bych přidala flag FILE_IGNORE_NEW_LINES, ať vám nenechává zalomení řádku u každého čísla.
pavel_pokorny
Profil
v zadání mohou být jen celá čísla s bílými znaky okolo, upravil jsem to takto, průmery to počítá.

Jen nevím jak zajistit, aby se v případě jiného znaku než čísla a whitespace vyhodila chyba

// post file
if(isset($_POST['submit']) && !empty($_FILES['file']['name'])) {
    $file = $_FILES['file']['name'];
    // parse file
    $parse = explode('.', $file);
    $pripona = $parse[1];
    
    // must be file .txt or .csv
    if($pripona == 'txt' or $pripona == 'csv') {
       $file_tmp = $_FILES['file']['tmp_name'];
       
       // file open
       $fileOpen = file($file_tmp);
       
       $hodnota = array();
       
       for($i=0; $i < count($fileOpen); $i++) {
           $hodnota[] = $fileOpen[$i];
       }
       
       
            // filtering values
            $uprava = array_filter($hodnota, create_function('$hodnota','return preg_match("#\S#", $hodnota);'));
            $prumer = array_sum($hodnota)/count($uprava);
      
            
       
    } else {
       $_error = 'Chyba: Nahráváte nepovolený formát souboru!';
    }
    
} else {
    $_error = 'Chyba: Nenahráváte žádný soubor!';
}
Tori
Profil
Porovnejte počet položek v polích $hodnota a $uprava, pokud se liší, tak některá položka nevyhovovala.
pavel_pokorny
Profil
to jde, ale moho tam byt i prázdné řádky, tak to by mi porovnání házelo chybu
Chro
Profil
Jestli ti mohu poradit v jiné věci a to kontrole povolených přípon souboru. Nejprve kontroluj, zda název souboru obsahuje tečku, třeba funkcemi strpos nebo substr_count. Pokud ano, rozděl název souboru podle tečky funkcí explode do pole, vytáhni poslední položku funkcí end a tu dále porovnávej. Zamezíš tak problému, pokud bude název souboru tř. data.od.pepy.csv
Tori
Profil
pavel_pokorny:
moho tam byt i prázdné řádky
, ale nemusejí: $fileOpen = file($file_tmp, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
peta
Profil
Chro:
"třeba funkcemi strpos"
Neni lepsi strrpos? Zrovna ziskas pozici tecky pocitanou od konce, pak pouzijes substr a nemusis nic explodovat.
Chro
Profil
peta:
To je samozřejmě také platný postup. Možná o něco rychlejší, možná s o jednou funkcí méně... Použil jsem ten, který mi vyhovoval v jednom ze skriptů. Potřeboval jsem totiž kontrolovat i možnou "předpříponu" uploadovaného souboru, př. soubor.jpg.zip.
pavel_pokorny
Profil
upravil jsem to parsovani
// parse file
    $pozice = strrpos($file, '.');
    $pozice = $pozice-1;
    $pripona = substr($file, '-'.$pozice);

ale porář mi to bere v potaz i jine znaky než čísla, potřebuju, aby se v případě jiného znaku než čísla vyhodila chyba
Chro
Profil
Pro kontrolu, zda je řetězec složen jen z číslic, lze použít funkci ctype_digit(), která vrací TRUE/FALSE.
pavel_pokorny
Profil
ctype_digit nezabralo, vrací to pokaždé chybu, nešlo by to nějak třeba přes preg_match?

if(ctype_digit($hodnota) == true) {

          // filtering values
            $uprava = array_filter($hodnota, create_function('$hodnota','return preg_match("#\S#", $hodnota);'));
            $prumer = array_sum($hodnota)/count($uprava);
            
} else {
            echo = 'chyba';
}
peta
Profil
Slo, sak si to najdi v dokumentaci mezi priklady nebo na regexp.
Tezko rici, proc ti to nefunguje, kdyz jsi nedal seznam vstupnich hodnot pro $hodnota do scriptu (schazi tam radek $hodnota = 'neco';).
http://cz1.php.net/preg_match
http://www.regexp.cz/ - [:digit:]
http://cz1.php.net/ctype_digit - mi prijdou example 1 a 2 jasne a vypadaji funkcne, netestoval jsem
pavel_pokorny
Profil
seznam vstupních hodnot

$hodnota = array('6', '-66', 'ahoj', '66', '6');

potřebuju z toho průměr tedy ať bere i záporná čísla
Alphard
Profil
$hodnota = array_filter($hodnota, function($v) { return is_numeric($v); } );
Modernější hezčí zápis anonymní funkce.
pavel_pokorny
Profil
povedlo se, funguje jak má

Děkuji všem moc za rady

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: