نوشتن و خواندن فایل ها با PHP — به زبان ساده

۵۱۱ بازدید
آخرین به‌روزرسانی: ۰۸ مهر ۱۴۰۲
زمان مطالعه: ۸ دقیقه
نوشتن و خواندن فایل ها با PHP — به زبان ساده

در این راهنما با چند تابع مهم در PHP آشنا می‌شویم که برای همه کارهای مورد نیاز در زمینه نوشتن و خواندن فایل ها در این زبان برنامه‌نویسی کافی هستند. در این مقاله روش خواندن یک فایل، نوشتن یک فایل، نوشتن یک فایل متنی و بررسی وجود یک فایل را بررسی می‌کنیم.

خوشبختانه PHP تابع‌های زیادی برای خواندن و نوشتن داده‌ها در فایل‌ها ارائه کرده است. در این راهنما ساده‌ترین روش برای خواندن داده‌ها از یک فایل محلی یا ریموت و چگونگی نوشتن فایل‌ها دقیقاً مطابق یک روش دلخواه با استفاده از فلگ‌ها معرفی خواهد شد.

بررسی وجود یک فایل

نخستین گام هنگام تلاش برای خواندن داده‌ها از یک فایل یا نوشتن چیزی در آن‌ها، بررسی وجود یا عدم وجود فایل است. تلاش برای خواندن از فایلی که وجود ندارد، موجب اعلان خطایی از سوی PHP می‌شود و احتمالاً باعث از کار افتادن کد نیز خواهد شد.

ساده‌ترین راه برای بررسی این که فایلی وجود دارد یا نه، استفاده از تابع (file_exists($filename در PHP است. دستور فوق در صورتی که یک فایل یا دایرکتوری با مقدار filename$ موجود باشد، مقدار true و در غیر این صورت مقدار false باز می‌گرداند. این وضعیت بدیهی است؛ اما باید اشاره کنیم که لزومی ندارد filename$ تنها نام یک فایل باشد. در واقع filename$ می‌تواند یک مسیر مطلق یا نسبی نیز باشد. برای نمونه می‌توانیم از prime_numbers.txt یا science/project/periodic_table.txt نیز استفاده کنیم.

همچنین باید به خاطر داشته باشیم که این تابع برای فایل‌هایی که به دلیل محدودیت‌های safe mode قابل دسترسی نیستند، نیز مقدار false باز می‌گرداند.

تابع دیگری که می‌تواند وجود یک فایل را بررسی کند، تابع ()is_file است. این تابع برخلاف ()file_exists تنها در صورتی که مسیر مشخص شده به یک فایل و نه دایرکتوری اشاره کرده باشد، مقدار true باز می‌گرداند.

اطمینان یافتن از این که فایل واقعاً وجود دارد

اگر کدی که می‌نویسید قرار است عملیات زیادی را روی یک فایل خاص انجام دهد، در صورت استفاده از تابع‌های فوق ممکن است، نتایج نادرستی دریافت کنید. دلیل این مسئله آن است که نتایج اجرای هر دو تابع ()file_exists و ()is_file جهت بهبود عملکرد، کَش می‌شوند. PHP نیز مقادیر بازگشتی از تابع‌های سیستم فایل مانند ()filesize() ،filemtime و غیره را کش می‌کند.

در این حالت می‌توانیم تابع ()clearstatcache را فراخوانی کنیم تا مطمئن شویم که هر اطلاعاتی که از یک فایل می‌خواهیم، به‌روز هستند. این وضعیت تنها در صورتی مشکل‌زا خواهد بود که یک فایل در اسکریپت خاصی چندین بار مورد بررسی قرار گیرد تا وضعیت آن مشخص شود. ضمناً داده‌های کش شده در صورتی پاک می‌شوند که فایل را درون اسکریپت با استفاده از تابع ()unlink حذف کنید. این وضعیت اساساً بدان معنی است که شما احتمالاً با هیچ مشکل کش کردن مواجه نخواهید شد؛ با این حال بهتر است با این واقعیت نیز آشنا باشید که در صورت کهنه شدن اطلاعات یا مشاهده نتایج غیر منتظره هنگام تلاش برای دسترسی به اطلاعاتی در مورد یک فایل، می‌توانید کش را پاک کنید.

خواندن داده‌ها از یک فایل در PHP

یکی از ساده‌ترین روش‌ها برای خواندن داده‌ها از یک فایل در PHP به کمک تابع زیر است:

file_get_contents($filename, $use_include_path, $context, $offset, $maxlen)

این تابع به سادگی کل فایل را خوانده و آن را به شکل یک رشته در اختیار شما قرار می‌دهد. همه پارامترها به جز پارامتر اول اختیاری هستند.

پارامتر دوم یک مقدار بولی می‌پذیرد تا تعیین کند که آیا به دنبال یک فایل در مکان مشخص شده از سوی مسیر include بگردد یا این که می‌تواند از تابع ()set_include_path استفاده کند.

می‌توان از پارامتر سوم برای تعیین دسته‌ای از گزینه‌ها برای تعیین دقیق چگونگی دسترسی به فایل‌ها نیز استفاده کرد. شما می‌توانید از این پارامتر برای تعیین مقادیر هدر مانند Cookies و Host و همچنین متد HTTP استفاده کنید.

پارامتر offset$ نقطه‌ای را مشخص می‌کند که خواندن داده‌ها در فایل اصلی آغاز خواهد شد. ارائه مقدار منفی باعث می‌شود که خواندن داده‌ها از انتهای فایل آغاز شود. پشتیبانی از این افست منفی تنها در نسخه 7.1.0 به بعد PHP اضافه شده است. همچنین لازم به ذکر است که این افست تنها در صورتی کار می‌کند که بخواهیم فایل‌های محلی را بخوانیم و در مورد فایل‌های ریموت پشتیبانی نمی‌شود.

تابع ()file_get_contents به صورت پیش‌فرض کل فایل را به یک باره می‌خواند. می‌توانید این رفتار را با ارائه مقداری برای پارامتر maxlen$ تغییر دهید. طول کاراکترهایی که باید خوانده شوند از مقدار افست شمارش می‌شود.

این تابع در صورتی که خواندن داده‌ها از فایل تعیین شده با مشکلی مواجه شود، مقدار false باز می‌گرداند. با این وجود، می‌تواند مقادیری نیز باز گرداند که به false تعبیر شوند، بنابراین باید با استفاده از عملگر (===) واقعاً مطمئن شوید که مقدار false بازگشت یافته است.

از این تابع می‌توان برای باز کردن فایل‌های ریموت نیز استفاده کرد؛ اما این حالت تنها در صورتی ممکن خواهد بود که مقدار گزینه allow-url-fopen در فایل php.ini برابر با true یا 1 تعیین شده باشد.

نوشتن داده‌ها در یک فایل به وسیله PHP

یکی از ساده‌ترین روش‌ها برای نوشتن داده‌ها در یک فایل با استفاده از PHP به کمک تابع زیر است:

file_put_contents($filename, $data, $flags, $context)

پارامتر filename$ تعیین می‌کند که داده‌ها در کدام فایل باید نوشته شوند. پارامتر دوم داده‌هایی است که باید در فایل نوشته شوند. در اغلب موارد این پارامتر یک رشته است؛ اما می‌تواند یک آرایه یا منبع جریان (stream) نیز باشد.

به خاطر داشته باشید که PHP در صورتی که فایل مورد نظر وجود نداشته باشد، به طور خودکار یک فایل با نام مفروض برای شما ایجاد می‌کند. با این وجود، نمی‌تواند دایرکتوری مورد نظر را نیز ایجاد کند. این بدان معنی است که می‌توانید یک فایل را با نام زیر بدون هیچ خطایی ایجاد کنید:

On the Origin of Species [Charles Darwin].txt

اما اگر مقدار filename$ برابر با عبارت زیر تعیین شده باشد:

Biology/Evolution/On the Origin of Species [Charles Darwin].txt

و مسیر Biology/Evolution/ موجود نباشد، با خطا مواجه خواهید شد.

پارامتر flags$ تعیین می‌کند که محتوای مورد نظر چگونه در فایل نوشته شود. این پارامتر می‌تواند یک یا چند مورد از (یا همه) مقادیر زیر را داشته باشد:

  • FILE_USE_INCLUDE_PATH – این مقدار به PHP اعلام می‌کند که در دایرکتوری include به دنبال نام فایل معین شده بگردد.
  • FILE_APPEND – این مقدار اعلام می‌کند که PHP باید داده‌هایی که به تابع ارسال می‌شوند را به داده‌های موجود در فایل الحاق کند. این پارامتر در مواردی مفید است که بخواهیم داده‌هایی مانند log یا خاطرات روزانه را در یک فایل ذخیره کنیم. بدین ترتیب ثبت کردن داده‌های جدید مانند دما یا رویدادهایی که در روز جاری رخ می‌دهند، باعث نمی‌شود که داده‌های مربوط به‌روز قبل حذف شوند.
  • LOCK_EX – این مقدار به PHP اعلام می‌کند که پیش از آغاز نوشتن محتوا در فایل، آن را قفل کند. بدین ترتب می‌توان از رخداد تغییرات ناخواسته هنگامی که دو اسکریپت داده‌ها را در فایلی می‌نویسند یا می‌خوانند جلوگیری کرد. با تعیین این مقدار خاص در واقع فایل قفل می‌شود. با مراجعه مستندات تابع ()flock می‌توانید در این مورد بیشتر مطالعه کنید.

این تابع در صورت موفقیت تعداد بایت‌هایی که در فایل نوشته شده‌اند؛ و در صورت شکست مقدار fasle باز می‌گرداند. با این وجود شما همچنان باید از عملگر (===) برای بررسی موفق بودن نوشتن محتوا در فایل استفاده کنید. دلیل این امر آن است که کدی که مقدار 0 بایت را با موفقیت در یک فایل نوشته است، همچنان به صورت false ارزیابی می‌شود.

خواندن و نوشتن داده‌ها در فایل‌ها

شما می‌توانید به وب‌سایت پروژه گوتنبرگ (+) مراجعه کرده و فایل‌ها را با استفاده از تابع ()file_get_contents دانلود کنید. زمانی که داده‌ها به شکل یک رشته باشند، می‌توانید آن‌ها را با استفاده از تابع ()file_put_contents نیز در یک فایل محلی ذخیره کنید. در مثال زیر این وضعیت به روشنی ارائه شده است:

<?php
 
$filename = 'http://www.gutenberg.org/cache/epub/1228/pg1228.txt';
 
$book_content = file_get_contents($filename);
file_put_contents('Biology/Evolution/On the Origin of Species [Charles Darwin].txt', $book_content, LOCK_EX);
 
?>

شما می‌توانید صفحه‌های وب یا محتواها را از وب‌سایت‌هایی مانند ویکی‌پدیا به روش مشابه ذخیره کنید. اگر می‌خواهید محتوای HTML معنی‌دار باشد یا آن را تحلیل کنید، کافی است آن را در یک فایل محلی ذخیره کنید و سپس با استفاده از DiDOM در PHP اقدام به تحلیل آن کرده و به طور خودکار لینک‌ها، فایل‌های تصاویر و دیگر اطلاعات مفید صفحه‌های وب را استخراج کنید.

در حال حاضر سعی می‌کنیم روی فایل‌های محلی متمرکز بمانیم. موقعیتی را تصور کنید که دسته‌ای از فایل‌های متنی دارید و می‌خواهید محتوای آن‌ها را بررسی کرده و چیزهایی مانند کلمات مشترک را بین آن‌ها بیابید. این نتیجه از طریق استفاده از چند تابع داخلی PHP به راحتی قابل حصول است:

?php
 
$filename = 'On the Origin of Species [Charles Darwin].txt';
$book_content = file_get_contents($filename);
 
$book_content_lowercase = strtolower($book_content);
 
$individual_words = explode(' ', $book_content_lowercase);
echo "There are about ".count($individual_words)." words in the book: ".substr($filename, 0, -4).".\n";
 
$word_frequency = array_count_values($individual_words);
echo "Total number of unique words in the book are ".count($word_frequency).".\n";
echo "The word 'Elephant' occurs ".$word_frequency["elephant"]." times in the book.\n";
echo "The word 'Ant' occurs ".$word_frequency["ant"]." times in the book.\n";
 
if(isset($word_frequency["evolution"])) {
    echo "The word 'Evolution' occurs ".$word_frequency["evolution"]." times in the book.\n";
} else {
    echo "The word 'Evolution' does not occur even once in the book.\n";
}
 
arsort($word_frequency);
echo "The most used word in the book is: '".key($word_frequency)."'.\n";
 
/* Output of all the code above
 
There are about 147520 words in the book: On the Origin of Species [Charles Darwin].
Total number of unique words in the book are 22758.
The word 'Elephant' occurs 3 times in the book.
The word 'Ant' occurs 6 times in the book.
The word 'Evolution' does not occur even once in the book.
The most used word in the book is: 'the'.
?>

ما همه متن را به حالت حروف کوچک تبدیل کردیم و فرض می‌کنیم که هر کلمه منفرد بر اساس اسپیس از دیگر کلمات جدا می‌شود. سپس این متن با استفاده از تابع ()explode به یک آرایه تبدیل می‌شود تا تحلیل کلمه‌های منفرد آسان‌تر شود. جای شگفتی است که در کتابی که به ریشه تکامل می‌پردازد، حتی یک بار نیز به کلمه «تکامل» (evolution) اشاره نشده است.

این تنها یک نمونه از تحلیل خودکار حجم بالایی از متن بود. شما می‌توانید کارهای مشابهی را روی هر نوع متنی که در یک فایل ذخیره شده است انجام دهید.

Log کردن داده‌ها با FILE_APPEND

یک مثال مفید دیگر log کردن یا گزارش‌گیری اطلاعات در طی بازه‌های زمانی کوتاه است. این وضعیت در موارد مختلفی مانند ثبت وضعیت تمرینات ورزشی، داده‌های هواشناسی یا کولنی زنبور عسلی که مورد مشاهده قرار می‌گیرد، پیش می‌آید. زمانی که داده‌های مورد نیاز خود را به صورت یک رشته در بیاورید، می‌توانید آن‌ها را به سادگی با استفاده از ()file_put_contents در یک فایل قرار داده و یا با استفاده فلگ FILE_APPEND به داده‌های موجود در فایل الحاق کنید.

<?php
 
$filename = "bee-colony.txt";
 
$present = date('l | jS \of F Y h:i:s A', time());
$entry = $present."\n";
 
// A pseudo function which could be replaced with something real.
$bee_information = gather_bee_data();
$entry .= "$bee_information.\n\n";
 
file_put_contents($filename, $entry, FILE_APPEND|LOCK_EX);
 
?>

می‌توان از کد مشابهی برای کارهایی مانند ذخیره‌سازی روزمره مقاله‌های برتر ویکی‌پدیا یا ردگیری مقالات خبری و عناوین آن‌ها در طی دوره هفتگی یا ماهانه استفاده کرد. تنها کاری که مورد نیاز است، نوشتن کدی برای اسکرپ کردن داده‌ها و سپس ذخیره‌سازی آن با استفاده از چیزی مانند قطعه کد فوق است.

همچنین به جای نوشتن فایل‌های متنی ساده می‌توان آن را درون برخی تگ‌های HTML قرار داد تا خواندن آن در مرورگرها راحت‌تر شود. در واقع امکاناتی که با استفاده از تابع‌های PHP به دست می‌آورید بی‌شمار هستند.

سخن پایانی

روش‌های مختلف دیگری برای خواندن و نوشتن داده‌ها در فایل با استفاده از PHP وجود دارد. با این حال، تابع‌های ()file_get_contents و ()file_put_contents تقریباً همه نیازهای اساسی را بدون نیاز به تابع‌های تکمیلی غیرضروری دیگر رفع می‌کنند.

تنها مواردی که ممکن است با مشکلی در مورد تابع ()file_get_contents مواجه شوید، زمانی است که یک فایل خیلی بزرگ مثلاً با اندازه 2 گیگابایت یا بیشتر را می‌خوانید. دلیل این امر آن است که تابع ()file_get_contents کل فایل را به یک باره درون حافظه بارگذاری می‌کند و این احتمال هست که با بارگذاری چنین فایل‌های بزرگی با کمبود حافظه مواجه شوید. در این حالت باید از تابع‌هایی مانند ()fgets و ()fread برای خواندن بخش‌های کوچکی از فایل در هر مرحله استفاده کنید.

اگر این مطلب برایتان مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۷ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
tutsplus
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *