Показать сообщение отдельно

  #6  
Старый 19.12.2008, 14:49
ss88
Участник форума
Регистрация: 27.11.2008
Сообщений: 161
С нами: 9185589

Репутация: 128
Wink

Цитата:
Сообщение от Gifts  
ss88, Naydav Омг, что за ужос вы пишете в час ночи?) Для больших файлов Бог давно придумал fgets и stream_get_line. fgets для построчного чтения, стрим - для любого разделителя
изменил кое-что, но твой вариант со взятием каждой строки отдельно - это для больших файлов, конечно, самое оно, я не подумавши только что запустил такой вариант, уже минут 10 чиргыкает 100Мб...
Но кое-что я таки поменял, за что тебе спасиобо
PHP код:
<?php
    $startTime
=microtime(TRUE);//приблизительный замер времени начала
    
$db=mysql_connect("localhost","root","");
    
mysql_select_db("achat",$db);
    
//убираем лимит по времени и аборты от пользователя
    
set_time_limit(0);
    
ignore_user_abort(TRUE);
    
$currPos=0;//текущая позиция в байтах
    
$delimiter='*';
    
$hFile=fopen("dump.txt","rt");
    
$partSize=51200;//одна порция = 50Кб
    
$currPos=0;//текущая позиция в байтах, считая от начала файла
    
$fileSize=filesize("dump.txt");//размер файла
    
echo "<b>Размер исходного файла:</b> ".($fileSize/1048576)."Mb ({$fileSize}Bytes)<br/>";
    
//дочитыване до конца последней строки
    
while(!feof($hFile))
    {
//если осталось в файле меньше,чем на порцию
        
if($currPos+$partSize>$fileSize)
            
$partSize=$fileSize-$currPos;
        
//считывание порции определенного размера
        
$currentPartOfData=fread($hFile,$partSize);
        
$currPos+=$partSize
        
/* если последний символ не разделитель строк, то нужно дочитать порцию до разделителя*/
        
if($currentPartOfData{strlen($currentPartOfData)-1}!=$delimiter
        {        
                
$currentPartOfData.=$tmp=stream_get_line($hFile,$partSize,$delimiter);
                
$currPos+=strlen($tmp)-1;
        }
        
/*НАГРУЗКА - разбить порцию на массив*/
        
$currentPartOfData=explode($delimiter,$currentPartOfData);
        
/*занесение значений в базу данных*/
        
foreach ($currentPartOfData as $string)
            
mysql_query("INSERT INTO gruz (str) VALUES('{$string}');",$db);
        echo 
"#";
    }
    echo 
$currentPartOfData[count($currentPartOfData)-1]."<br/>";
    
fclose($hFile);
    
mysql_close($db);
    echo 
"<br/>endPos={$currPos}<br/><b>Время затраченное на операцию: </b>".(microtime(TRUE)-$startTime)." seconds";
?>
кстати, теперь, когда окончание строки выдирается stream_get_line работает с такой же скоростью. А вот все таки вариант с построчным выдиранием - это не то ))) запусти такое у себя, когда файл из строк символов по 200-300, а сам файл метров 100-200, мне пришлось рестартить апач, чтобы эта медленная садистская вакханалия прекратилась. )))
Вобщем-то, закономерно, что, при уменьшении размера порции, увеличится время выполнения, но и нужно задуматься перед тем, как ставить ее больше одного Мб. Хотя наибольшего быстродействия чтение/разбиение я добился при размере порции 50Кб. 20Мб без занесения в БД обрабатывается 0,2с. Так что, уже стало ясно, по крайней мере мне, что при средних размерав дампов в 40-100Мб, операция их чтения/обработки/занесения в БД совсем даже и не критичны в таком контексте выполнения.

Последний раз редактировалось ss88; 19.12.2008 в 16:01..
 
Ответить с цитированием