Menu

file_get_contents() ב-PHP: קריאת קובץ למחרוזת

file_get_contents('notes.txt') קוראת קובץ שלם ומחזירה אותו כמחרוזת אחת, או false אם היא לא מצליחה. השותפה שלה file_put_contents() כותבת מחרוזת לקובץ, ו-file() מחזירה את השורות כמערך.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

file_get_contents('notes.txt') קוראת את כל הקובץ ומחזירה אותו כמחרוזת אחת. אם אי אפשר לקרוא את הקובץ היא מחזירה false. כדי לכתוב, השתמשו ב-file_put_contents('notes.txt', $text), שיוצרת את הקובץ או מחליפה את מה שהיה בו.

פלט:

Buy milk
Call Ada
Write docs
29 bytes
3 lines

הבלוק כותב קודם את notes.txt ואז קורא אותו בחזרה, כדי שיהיה לו קובץ לעבוד איתו. נתיב כמו 'notes.txt' יחסי לתיקיית העבודה הנוכחית; באפליקציית web, בנו את הנתיב מהתיקייה של הסקריפט עצמו עם __DIR__ . '/notes.txt'.

כתיבה והוספה עם file_put_contents()

file_put_contents() מחזירה את מספר הבתים שנכתבו, או false בכישלון. כברירת מחדל היא דורסת את הקובץ. הדגל FILE_APPEND מוסיף לסוף במקום זאת, וכך עובדים לוגים פשוטים, ו-LOCK_EX מונע משתי בקשות לכתוב באותו רגע:

פלט:

Wrote 8 bytes
started
step 1 done
step 2 done

replaced

abc
5 bytes

כדי לשמור מערך ולקבל אותו בחזרה כמערך, כתבו אותו כ-JSON עם json_encode() וקראו אותו עם json_decode().

קריאת קובץ שורה אחר שורה עם file()

file() קוראת קובץ למערך עם שורה אחת בכל איבר. כל שורה שומרת על ירידת השורה שבסופה אלא אם מעבירים FILE_IGNORE_NEW_LINES, ו-FILE_SKIP_EMPTY_LINES משמיט שורות ריקות (הוא עובד רק יחד עם FILE_IGNORE_NEW_LINES):

פלט:

string(9) "Buy milk
"
1. Buy milk
2. Call Ada
3. Write docs
3 tasks

file() ו-file_get_contents() טוענות את כל הקובץ לזיכרון. זה בסדר לקובצי הגדרות וללוגים של כמה מגה-בתים. לקובץ של מאות מגה-בתים, קראו אותו שורה אחר שורה עם fopen() ו-fgets() במקום זאת.

בדיקה אם קובץ קיים לפני הקריאה

כשהקובץ חסר, file_get_contents() מחזירה false ו-PHP מדפיסה אזהרה:

Warning: file_get_contents(missing.txt): Failed to open stream: No such file or directory in /home/index.php on line 2

בדקו קודם עם is_file() (קובץ שקיים ואינו תיקייה) או עם file_exists() (קובץ או תיקייה), ותמיד השוו את התוצאה עם === false, כי קובץ ריק מחזיר "", שגם הוא שקרי:

פלט:

empty.txt   exists file 
missing.txt missing 
.           exists directory 
Cannot read missing.txt, using defaults
bool(false)
bool(true)
0 bytes

אל תסתירו את האזהרה עם @file_get_contents(). בדיקה מראש, או טיפול ב-false, שומרים על השגיאה גלויה כשמשהו אחר משתבש.

קריאת חלק מקובץ

הארגומנטים הרביעי והחמישי הם היסט הבתים שממנו מתחילים ומספר הבתים לקריאה. היסט שלילי נספר מסוף הקובץ. ארגומנטים בשם מאפשרים לדלג על שני הארגומנטים שבאמצע:

פלט:

HEADER
line 2
last line

היסטים סופרים בתים, לא תווים. ב-UTF-8 תו יפני הוא 3 בתים, ולכן היסט באמצע תו כזה חותך אותו לשניים. כדי לעבוד עם תווים, קראו את כל המחרוזת והשתמשו ב-mb_substr().

הצגת קובץ טקסט בדף אינטרנט

תוכן של קובץ הוא טקסט, וטקסט שמודפס לתוך HTML חייב לעבור escape, אחרת < בקובץ הופך לתגית. htmlspecialchars() מבצעת לו escape ו-nl2br() הופכת את ירידות השורה לתגיות <br>. הריצו את זה והסתכלו בלשונית Page:

הסירו את htmlspecialchars() והריצו שוב: הדף מסתיים עכשיו ב-"v1.2: Fixed", כי הדפדפן קורא את <title> כתגית אמיתית ובולע את כל מה שאחריה ככותרת הדף. העמוד htmlspecialchars() מסביר למה זה חשוב לכל דבר שמשתמש יכול לכתוב.

קריאת URL עם file_get_contents()

כש-allow_url_fopen מופעל (ברירת המחדל ב-php.ini), file_get_contents() קוראת גם כתובות URL ומחזירה את גוף התשובה. stream context מוסיף method, כותרות, גוף ו-timeout:

<?php
$html = file_get_contents('https://example.com/');

$context = stream_context_create([
    'http' => [
        'method'  => 'POST',
        'header'  => "Content-Type: application/json\r\n",
        'content' => json_encode(['name' => 'Ada']),
        'timeout' => 5,
        'ignore_errors' => true,   // return the body of 4xx/5xx responses too
    ],
]);

$response = file_get_contents('https://api.example.com/users', false, $context);
if ($response === false) {
    // DNS failure, timeout, or a refused connection
}

לניסיונות חוזרים, הפניות עם מגבלות וקודי שגיאה ברורים, cURL או ספריית לקוח HTTP כמו Guzzle הם הכלי הטוב יותר.

file_get_contents מול file() מול fopen()

אתם רוציםהשתמשו בזיכרון
את כל הקובץ כמחרוזת אחתfile_get_contents()כל הקובץ
את השורות כמערךfile($path, FILE_IGNORE_NEW_LINES)כל הקובץ
לכתוב או להחליף קובץ בקריאה אחתfile_put_contents()הנתונים שכותבים
להוסיף שורה ללוגfile_put_contents($path, $line, FILE_APPEND | LOCK_EX)שורה אחת
לקרוא קובץ גדול שורה אחר שורה, או שורות CSVfopen() עם fgets() או fgetcsv()שורה אחת
לקרוא ולכתוב באותו קובץ פתוחfopen() עם r+, a+ או c+מה שקוראים

הפונקציות של קריאה אחת פותחות, קוראות או כותבות, וסוגרות את הקובץ בשבילכם, ולכן הן ברירת המחדל הנכונה. פנו ל-fopen() כשהקובץ גדול מכדי להחזיק בזיכרון או כשאתם צריכים להשאיר אותו פתוח בין פעולות.

שאלות נפוצות

איך קוראים קובץ למחרוזת ב-PHP?

קראו ל-file_get_contents('path/to/file.txt'). היא מחזירה את הקובץ כולו כמחרוזת, או false אם אי אפשר לקרוא את הקובץ, אז השוו את התוצאה עם === false לפני שמשתמשים בה.

איך מוסיפים לסוף קובץ ב-PHP?

העבירו את הדגל FILE_APPEND: file_put_contents('log.txt', "new line\n", FILE_APPEND);. בלעדיו, file_put_contents() מחליפה את כל הקובץ. הוסיפו LOCK_EX (FILE_APPEND | LOCK_EX) כשכמה בקשות עשויות לכתוב באותו זמן.

איך קוראים קובץ שורה אחר שורה ב-PHP?

לקבצים קטנים, file('data.txt', FILE_IGNORE_NEW_LINES) מחזירה מערך עם שורה אחת בכל איבר. לקבצים גדולים, פתחו אותו עם fopen() וקראו שורה אחת בכל פעם עם fgets() בלולאת while, שמחזיקה רק שורה אחת בזיכרון.

למה file_get_contents מחזירה false?

הקובץ לא קיים, הנתיב יחסי לתיקייה אחרת ממה שאתם חושבים, או של-PHP אין הרשאה לקרוא אותו. PHP גם מדפיסה אזהרה כמו Failed to open stream: No such file or directory. בדקו עם is_file() ו-is_readable(), ובנו נתיבים מ-__DIR__.

האם file_get_contents יכולה לקרוא URL?

כן, כש-allow_url_fopen מופעל ב-php.ini: file_get_contents('https://example.com/') מחזירה את גוף התשובה. לכותרות, לנתוני POST או ל-timeout, העבירו context מ-stream_context_create(); לכל דבר מורכב יותר, cURL נותן טיפול טוב יותר בשגיאות.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל