Я хочу разбить огромные файлы (в частности, файлы tar.gz) в нескольких частях из php-кода. Основная причина для этого – ограничение 2gb php на 32-битную систему.
Я хочу разбить большие файлы в несколько частей и обрабатывать каждую часть отдельно.
Это возможно? Если да, то как?
Простым методом (при использовании Linux-сервера) является использование команды exec
и запуск команды split
:
exec('split Large.tar.gz -b 4096k SmallParts'); // 4MB parts /* | | | | | | | |______| | App | | |_____________ The source file | | The split size Out Filename */
Подробнее см. Здесь: http://www.computerhope.com/unix/usplit.htm
Или вы можете использовать: http://www.computerhope.com/unix/ucsplit.htm
exec('csplit -k -s -f part_ -n 3 LargeFile.tar.gz');
PHP работает в одном потоке, и единственный способ увеличить этот счетчик потоков – создать дочерний процесс, используя команды fork
.
Это не подходит для ресурсов. Я бы предложил изучить язык, который может сделать это быстро и эффективно. Я бы предложил использовать node.js.
Просто установите узел на сервере, а затем создайте небольшой скрипт, например node_split
, который может выполнить эту работу самостоятельно для вас.
Но я настоятельно рекомендую вам не использовать PHP для этой работы, но использовать exec, чтобы позволить операционной системе хоста сделать это.
Мой комментарий был проголосован дважды, так что, возможно, мое предположение было на что-то: P
Если в среде unix, попробуйте это …
exec('split -d -b 2048m file.tar.gz pieces');
Трещина
Ваши куски должны быть кусочками1, pieces2
и т. Д.
Вы можете получить количество полученных результатов легко, используя stat()
в PHP, чтобы получить размер файла, а затем выполните простую математику (int) ($stat['size'] / 2048*1024*1024)
(я думаю).
HJSplit
Возможно, сам PHP не сможет … Если вы можете понять, как это сделать из командной строки вашего компьютера, вы должны затем выполнить эти команды с помощью exec();
function split_file($source, $targetpath='/split/', $lines=1000){ $i=0; $j=1; $date = date("mdy"); $buffer=''; $handle = fopen ($_SERVER['DOCUMENT_ROOT'].$source, "r"); while (!feof ($handle)) { $buffer .= fgets($handle, 4096); $i++; if ($i >= $lines) { $fname = $_SERVER['DOCUMENT_ROOT'].$targetpath."part_".$date.$j.".txt"; $fhandle = fopen($fname, "w") or die($php_errormsg); if (!$fhandle) { echo "Cannot open file ($fname)"; //exit; } if (!fwrite($fhandle, $buffer)) { echo "Cannot write to file ($fname)"; //exit; } fclose($fhandle); $j++; $buffer=''; $i=0; $line+=10; // add 10 to $lines after each iteration. Modify this line as required } } fclose ($handle); }
$handle = fopen('source/file/path','r'); $f = 1; //new file number while(!feof($handle)) { $newfile = fopen('newfile/path/'.$f.'.txt','w'); //create new file to write to with file number for($i = 1; $i <= 5000; $i++) //for 5000 lines { $import = fgets($handle); //print_r($import); fwrite($newfile,$import); if(feof($handle)) {break;} //If file ends, break loop } fclose($newfile); $f++; //Increment newfile number } fclose($handle);
в$handle = fopen('source/file/path','r'); $f = 1; //new file number while(!feof($handle)) { $newfile = fopen('newfile/path/'.$f.'.txt','w'); //create new file to write to with file number for($i = 1; $i <= 5000; $i++) //for 5000 lines { $import = fgets($handle); //print_r($import); fwrite($newfile,$import); if(feof($handle)) {break;} //If file ends, break loop } fclose($newfile); $f++; //Increment newfile number } fclose($handle);
Вероятно, это возможно в php, но php был создан для веб-разработки, и попытка выполнить всю эту операцию в одном запросе приведет к отключению запроса.
Однако вы можете использовать другой язык, например java или c #, и создать фоновый процесс, который вы можете уведомить из php для выполнения операции. Или даже запустить с php, в зависимости от ваших настроек безопасности на хосте.
Разбиения называются filename.part0 filename.part1 …
<?php function fsplit($file,$buffer=1024){ //open file to read $file_handle = fopen($file,'r'); //get file size $file_size = filesize($file); //no of parts to split $parts = $file_size / $buffer; //store all the file names $file_parts = array(); //path to write the final files $store_path = "splits/"; //name of input file $file_name = basename($file); for($i=0;$i<$parts;$i++){ //read buffer sized amount from file $file_part = fread($file_handle, $buffer); //the filename of the part $file_part_path = $store_path.$file_name.".part$i"; //open the new file [create it] to write $file_new = fopen($file_part_path,'w+'); //write the part of file fwrite($file_new, $file_part); //add the name of the file to part list [optional] array_push($file_parts, $file_part_path); //close the part file handle fclose($file_new); } //close the main file handle fclose($file_handle); return $file_parts; } ?>