چگونه یک کد php را روی یک فایل سنگین اجرا کنیم؟
	
	
		درود
من یه کد php دارم که یه فایل txt رو باز میکنه. سپس کلیه لاین هایی که .com توی اونا باشه رو حذف میکنه
مثلا اگه یه فایل حاوی کلی دامین باشه، دامنه هایی که .com هستند رو از فایل حذف میکنه
	کد PHP:
	
<?php
$fname = "test.txt";
$lines = file($fname);
foreach($lines as $line) if(!strstr($line, ".com")) $out .= $line;
$f = fopen($fname, "w");
fwrite($f, $out);
fclose($f);
?>
 حالا وقتی این کد رو روی یه فایل سنگین که میلیون ها دامین توی اونه اجرا میکنم اجرا نمیشه!
راه حل این مشکل چیه؟
	 
	
	
	
		پاسخ : چگونه یک کد php را روی یک فایل سنگین اجرا کنیم؟
	
	
		خیلی منطقی تره ابتدا فایل رو واردsql بکنید ( داده هاشو )و بعد از طریق دیتابیس انجام بدید
	 
	
	
	
		پاسخ : چگونه یک کد php را روی یک فایل سنگین اجرا کنیم؟
	
	
		
	نقل قول:
	
		
		
			
				نوشته اصلی توسط 
rayanagostar
				 
			خیلی منطقی تره ابتدا فایل رو واردsql بکنید ( داده هاشو )و بعد از طریق دیتابیس انجام بدید
			
		
	 
 مشکل اینجاس که نمیخوام از طریق دیتابیس باشه
پروژه ای رو که میخوام پیاده کنم دیتابیس نباید داشته باشه...
	 
	
	
	
		پاسخ : چگونه یک کد php را روی یک فایل سنگین اجرا کنیم؟
	
	
		باسلام، اگر از file استفاده کنید با توجه به حجم فایل نیاز به مموری دارید، به طور مثال اگر فایل 500mb هست نیاز هست داخل PHP.INI محدودیت مموری را تنظیم کنید، اما اگر از fopen استفاده کنید چون اشاره گر هست اگر سیستم عامل 32 بیت است می توانید تا 2 گیگ فایل (به صورت stream) بارگذاری کنید، اگر بیشتر از 2 گیگ است باید سیستم عامل 64 بیت و PHP 7 استفاده کنید.
	کد:
	
$lines = file($fname);
 
	 
	
	
	
		پاسخ : چگونه یک کد php را روی یک فایل سنگین اجرا کنیم؟
	
	
		سلام
من با برنامه زیر یک فایل دیگه حاوی 21 میلیون آدرس دامنه (که تعداد دامنه com شانسی است) ایجاد کردم.
	کد PHP:
	
<?php
$chars = implode("", array_merge(range('a', 'z'), range('A', 'Z'), range('0', '9')));
$tlds = array('com', 'net', 'org', 'ir');
$file = fopen('domains.txt', 'a');
for($x = 0; $x < 21000000;$x++) {
    $length = rand(5,15);
    $tld = $tlds[rand(0, count($tlds) - 1)];
    $chars = str_shuffle($chars);
    fwrite($file, substr($chars, 0, $length).'.'.$tld."\n");
}
fclose($file);
 حجم فایل نهایتا 309.7 مگابایت شد.
با برنامه زیر آدرس های غیر com رو جدا کردم:
	کد PHP:
	
<?php
$source = fopen('domains.txt', 'r');
$dest = fopen("domains-filtered.txt", 'w');
while (($line = fgets($source, 128)) !== false) {
    if (substr(rtrim($line), -4) != ".com") {
        fwrite($dest, $line);
    }
}
fclose($source);
fclose($dest);
 این برنامه توی 44.97 ثانیه روی سیستم من اجرا شد و حجم فایل خروجی 231 مگابایت شد:
	کد:
	
➜  Desktop /usr/bin/time -v php b.php
    Command being timed: "php b.php"
    User time (seconds): 12.17
    System time (seconds): 32.01
    Percent of CPU this job got: 98%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:44.97
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 29392
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 2015
    Voluntary context switches: 4
    Involuntary context switches: 1069
    Swaps: 0
    File system inputs: 8
    File system outputs: 451232
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0
 
----------------------
هرچند که این سوال استاتر نبود اما برای خودم جالب بود که این بار همون فایل رو با یک زبان سطح پایینتر مقایسه کنم بنابراین من یکبار دیگه همون فایل قبلی رو با برنامه ی c پردازش کردم:
	کد:
	
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
    char * line = NULL;
    size_t len = 0;
    ssize_t read;
    char tld[5];
    
    FILE * source = fopen("./domains.txt", "r");
    if (source == NULL)
        exit(EXIT_FAILURE);
    FILE * dest = fopen("./domains-filtered.txt", "w");
    if (dest == NULL)
        exit(EXIT_FAILURE);
    while ((read = getline(&line, &len, source)) != -1) {
        memcpy( tld, &line[read - 5], 4);
        tld[4] = '\0';
        if (strcmp(tld, ".com")) {
            fwrite(line, 1, read, dest);
        }
    }
    fclose(source);
    fclose(dest);
    if (line)
        free(line);
    exit(EXIT_SUCCESS);
}
 این بار برنامه توی 2.61 ثانیه اجرا شد (حدودا 17 برابر سریعتر)
	کد:
	
➜  Desktop /usr/bin/time -v ./a.out
    Command being timed: "./a.out"
    User time (seconds): 1.34
    System time (seconds): 0.23
    Percent of CPU this job got: 60%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:02.61
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 1244
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 64
    Voluntary context switches: 6
    Involuntary context switches: 114
    Swaps: 0
    File system inputs: 0
    File system outputs: 451224
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0
 
	 
	
	
	
		پاسخ : چگونه یک کد php را روی یک فایل سنگین اجرا کنیم؟
	
	
		
	نقل قول:
	
		
		
			
				نوشته اصلی توسط 
T.Toosi
				 
			باسلام، اگر از file استفاده کنید با توجه به حجم فایل نیاز به مموری دارید، به طور مثال اگر فایل 500mb هست نیاز هست داخل PHP.INI محدودیت مموری را تنظیم کنید، اما اگر از fopen استفاده کنید چون اشاره گر هست اگر سیستم عامل 32 بیت است می توانید تا 2 گیگ فایل (به صورت stream) بارگذاری کنید، اگر بیشتر از 2 گیگ است باید سیستم عامل 64 بیت و PHP 7 استفاده کنید.
	کد:
	
$lines = file($fname);
 
	 
 سیستم عامل من ۶۴ بیتی هست و php7 استفاده میکنم
الان توی php.ini باید چی بنویسم؟
- - - Updated - - -
	نقل قول:
	
		
		
			
				نوشته اصلی توسط 
JeyServer
				 
			سلام
من با برنامه زیر یک فایل دیگه حاوی 
21 میلیون آدرس دامنه (که تعداد دامنه com شانسی است) ایجاد کردم.
	کد PHP:
	
<?php
$chars = implode("", array_merge(range('a', 'z'), range('A', 'Z'), range('0', '9')));
$tlds = array('com', 'net', 'org', 'ir');
$file = fopen('domains.txt', 'a');
for($x = 0; $x < 21000000;$x++) {
    $length = rand(5,15);
    $tld = $tlds[rand(0, count($tlds) - 1)];
    $chars = str_shuffle($chars);
    fwrite($file, substr($chars, 0, $length).'.'.$tld."\n");
}
fclose($file);
 حجم فایل نهایتا 309.7 مگابایت شد.
با برنامه زیر آدرس های غیر com رو جدا کردم:
	کد PHP:
	
<?php
$source = fopen('domains.txt', 'r');
$dest = fopen("domains-filtered.txt", 'w');
while (($line = fgets($source, 128)) !== false) {
    if (substr(rtrim($line), -4) != ".com") {
        fwrite($dest, $line);
    }
}
fclose($source);
fclose($dest);
 این برنامه توی 44.97 ثانیه روی سیستم من اجرا شد و حجم فایل خروجی 231 مگابایت شد:
	کد:
	
➜  Desktop /usr/bin/time -v php b.php
    Command being timed: "php b.php"
    User time (seconds): 12.17
    System time (seconds): 32.01
    Percent of CPU this job got: 98%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:44.97
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 29392
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 2015
    Voluntary context switches: 4
    Involuntary context switches: 1069
    Swaps: 0
    File system inputs: 8
    File system outputs: 451232
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0
 
----------------------
هرچند که این سوال استاتر نبود اما برای خودم جالب بود که این بار همون فایل رو با یک زبان سطح پایینتر مقایسه کنم بنابراین من یکبار دیگه همون فایل قبلی رو با برنامه ی c پردازش کردم:
	کد:
	
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
    char * line = NULL;
    size_t len = 0;
    ssize_t read;
    char tld[5];
    
    FILE * source = fopen("./domains.txt", "r");
    if (source == NULL)
        exit(EXIT_FAILURE);
    FILE * dest = fopen("./domains-filtered.txt", "w");
    if (dest == NULL)
        exit(EXIT_FAILURE);
    while ((read = getline(&line, &len, source)) != -1) {
        memcpy( tld, &line[read - 5], 4);
        tld[4] = '\0';
        if (strcmp(tld, ".com")) {
            fwrite(line, 1, read, dest);
        }
    }
    fclose(source);
    fclose(dest);
    if (line)
        free(line);
    exit(EXIT_SUCCESS);
}
 این بار برنامه توی 2.61 ثانیه اجرا شد (حدودا 17 برابر سریعتر)
	کد:
	
➜  Desktop /usr/bin/time -v ./a.out
    Command being timed: "./a.out"
    User time (seconds): 1.34
    System time (seconds): 0.23
    Percent of CPU this job got: 60%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:02.61
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 1244
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 64
    Voluntary context switches: 6
    Involuntary context switches: 114
    Swaps: 0
    File system inputs: 0
    File system outputs: 451224
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0
 
	 
 کد شما به خوبی کار میکنه... چرا کد من کار نمیکرد؟
	 
	
	
	
		پاسخ : چگونه یک کد php را روی یک فایل سنگین اجرا کنیم؟
	
	
		
	نقل قول:
	
		
		
			
				نوشته اصلی توسط 
سیدرضا بازیار
				 
			
الان اکه بخواید با همون کد فقط دامنه های .com رو جدا کنید چیکار میکنید؟ عمل میکنه؟
			
		
	 
 توی خط پنجم برنامه بالا،علامت تعجب (!) رو به (=) تبدیل کنید.
در نهایت:
	کد PHP:
	
 <?php
$source = fopen('domains.txt', 'r');
$dest = fopen("domains-filtered.txt", 'w');
while (($line = fgets($source, 128)) !== false) {
    if (substr(rtrim($line), -4) == ".com") {
        fwrite($dest, $line);
    }
}
fclose($source);
fclose($dest);
 
	 
	
	
	
		پاسخ : چگونه یک کد php را روی یک فایل سنگین اجرا کنیم؟
	
	
		
	نقل قول:
	
		
		
			
				نوشته اصلی توسط 
JeyServer
				 
			توی خط پنجم برنامه بالا،علامت تعجب (!) رو به (=) تبدیل کنید.
در نهایت:
	کد PHP:
	
 <?php
$source = fopen('domains.txt', 'r');
$dest = fopen("domains-filtered.txt", 'w');
while (($line = fgets($source, 128)) !== false) {
    if (substr(rtrim($line), -4) == ".com") {
        fwrite($dest, $line);
    }
}
fclose($source);
fclose($dest);
 
	 
 درسته. چون متوجه شدم ویرایش کردم...
فقط برام سواله که چرا کد من کار نکرد؟ مشکل کد من چی بود؟
	 
	
	
	
		پاسخ : چگونه یک کد php را روی یک فایل سنگین اجرا کنیم؟
	
	
		
	نقل قول:
	
		
		
			
				نوشته اصلی توسط 
سیدرضا بازیار
				 
			کد شما به خوبی کار میکنه... چرا کد من کار نمیکرد؟
			
		
	 
 چون شما از تابع file استفاده کرده بودید، این تابع ابتدا کل فایل رو بصورت خط به خط میخونه و هر خط رو در یک خونه آرایه ذخیره میکنه.
دراینصورت شما به حجم کل فایل رم استفاده میکنید چون کل فایل رو از روی هارد خوندید، خط به خط جدا کردید و روی RAM ذخیره کردید و این میتونه خیلی در بازدهی برنامه چالش برانگیز باشه.
من به جای file() از توابع fopen و fgets استفاده کردم. تابع fgets یک خط از فایل رو میخونه و بعد از اینکه کار شما با اون خط تموم شد، فراموشش میکنه و بنابراین دیگه مهم نیست که حجم فایل شما چقدر باشه، همیشه منابع اشغال شده در حداقل خواهند بود.
همینطور شما بعد از جداسازی خط های مورد نظر اون هارو در یک متغییر ذخیره میکردید، یعنی مجددا به اندازه حجم فایل خروجی رم استفاده میکردید، من به جای اینکه دامنه هارو ذخیره کنم تا در نهایت یکجا همه رو ذخیره کنم، هر خط رو در همون لحظه ذخیره میکردم در نتیجه RAM مشغول نمیشه!