open#
משייך מטפל קובץ לקובץ, לפקודה, או לסקלר בזיכרון.
open היא הדרך הראשית שבה תוכנית Perl רוכשת מטפל קובץ. צורת שלושת־הארגומנטים - open $fh, MODE, EXPR - היא זו שיש להשתמש בה בקוד חדש: המצב מצוין במפורש, שם הקובץ אינו יכול להתפרש מחדש כשרשרת shell, ורווחים מובילים או נגררים ב־EXPR נשמרים מילולית. צורת שני־הארגומנטים הישנה יותר קיימת לתאימות ולפירוש שם הקובץ ה״קסום״ שהיא מאפשרת; אל תזינו לה קלט בלתי־מהימן.
תקציר#
open my $fh, "<", $path or die "read $path: $!";
open my $fh, ">", $path or die "write $path: $!";
open my $fh, ">>", $path or die "append $path: $!";
open my $fh, "+<", $path or die "rw $path: $!";
open my $fh, "<:encoding(UTF-8)", $path or die $!;
open my $mem, ">", \$buf or die $!; # in-memory
open my $pipe, "-|", "ls", "-la" or die $!; # read from cmd
open my $pipe, "|-", "gzip", ">$f" or die $!; # write to cmd
מה מקבלים בחזרה#
1 בהצלחה; undef בכשל, עם $! מוגדר לשגיאת ה־OS. עבור צורות ה־pipe (|- / -|), ערך ההחזרה בהצלחה הוא ה־pid של תהליך הילד - שימושי כשצריך לעשות waitpid עליו מאוחר יותר. לאחר open של pipe עם ארגומנט אחד או שניים על הפקודה המילולית -, open מחזיר פעמיים (ההורה מקבל את ה־pid של הילד, הילד מקבל 0); השתמשו ב־defined($pid) או // כדי להבחין בין השניים.
בדקו תמיד את ערך ההחזרה. open כושל משאיר את מטפל הקובץ סגור, וכל קריאה או כתיבה לאחר מכן עליו תקבע את $! ל־Bad file descriptor ותפיק אזהרה תחת use warnings.
open my $fh, "<", $path
or die "open $path: $!";
מצב גלובלי שהוא נוגע בו#
$!- נקבע בכשל לשגיאה ברמת ה־OS.${^OPEN}- שכבות I/O ברירת מחדל המותקנות על־ידי הפראגמהopenאו המתג-CioD. אלה חלות רק כאשרMODEבצורת שלושת־הארגומנטים אינו מכיל שכבה מפורשת;<או>עירומים מכבדים אותן,<:rawאו כל שכבה מפורשת אחרת מדכאת אותן.$^F- ה־file descriptor הגבוה ביותר שאינו מסומן close-on-exec; ה־fd החדש יורש את דגל close-on-exec בהתבסס על זה.מטפל קובץ נבחר דרך
select- אינו משתנה על־ידיopen, אך הופך לרלוונטי ברגע ש־printלמטפל החדש מבלי לנקוב בשמו.עבור צורות pipe,
$?ו־${^CHILD_ERROR_NATIVE}נקבעים כאשר המטפל נסגר מאוחר יותר.
מצבים#
הארגומנט השני נוקב בתפקיד I/O. המקרים הנפוצים:
מצב | משמעות | מקבילה ב־ |
|---|---|---|
| קריאה |
|
| כתיבה, חיתוך או יצירה |
|
| הוספה בסוף, יצירה אם חסר |
|
| קריאה וכתיבה, ללא חיתוך |
|
| קריאה וכתיבה, חיתוך תחילה |
|
| pipe לפקודה (אנחנו כותבים) | - |
| pipe מפקודה (אנחנו קוראים) | - |
| dup או fdopen על מטפל קיים | - |
קבצים חדשים שנוצרו מקבלים הרשאות 0666 & ~umask. +< הוא כמעט תמיד מה שרוצים לקריאה־כתיבה; +> דורס את הקובץ תחילה.
שכבות I/O מתחברות לאחר המצב: <:encoding(UTF-8), >:raw, >>:crlf, <:encoding(UTF-8):crlf. שכבה מפורשת מדכאת את ברירות המחדל של ${^OPEN}; נקודתיים בודדות (<:) חוזרות לברירת המחדל של ה־OS (:raw ב־Unix, :crlf ב־Windows).
דוגמאות#
קריאת קובץ טקסט UTF-8 שורה אחר שורה:
open my $fh, "<:encoding(UTF-8)", "notes.txt"
or die "open notes.txt: $!";
while (my $line = <$fh>) {
chomp $line;
# ... use $line ...
}
close $fh or warn "close: $!";
כתיבת קובץ בינארי ללא תרגום קידוד:
open my $out, ">:raw", "image.bin"
or die "open image.bin: $!";
print $out $bytes;
close $out or die "close: $!";
מטפל קובץ בזיכרון - print לתוך סקלר, שימושי ללכידת פלט המצפה למטפל אמיתי:
my $buf = "";
open my $mem, ">", \$buf or die $!;
print $mem "hello\n";
close $mem;
# $buf now contains "hello\n"
קריאה מפקודה, בצורת רשימה כך שהארגומנטים אינם כפופים לפירוש מטה־תווים של ה־shell:
open my $ls, "-|", "ls", "-la", $dir
or die "ls: $!";
while (<$ls>) { print }
close $ls; # $? holds the exit status
קובץ אנונימי זמני - העבירו undef כארגומנט השלישי עם מצב קריאה־כתיבה, ואז seek חזרה להתחלה כדי לקרוא את מה שכתבתם:
open my $tmp, "+>", undef or die $!;
print $tmp "scratch data\n";
seek $tmp, 0, 0;
my $line = <$tmp>;
מקרי קצה#
open ״קסום״ בשני־ארגומנטים:
open $fh, $nameמכבד<,>,>>מובילים,|נגרר, ומסיר רווחים סובבים מ־$name. בסדר עבור שם קובץ מילולי שהקלדתם בעצמכם; לעולם לא עבור שם קובץ שהגיע מקלט משתמש, מהרשת, או ממשתנה סביבה. השתמשו בצורת שלושת־הארגומנטים.-בשני־ארגומנטים:open $fh, "<-"אוopen $fh, "-"פותח אתSTDIN;open $fh, ">-"פותח אתSTDOUT. המקבילות בשלושה־ארגומנטים הןopen $fh, "<", "-"ו־open $fh, ">", "-".פתיחה מחדש של
STDOUT/STDERR: סגרו אותם תחילה, ואז פתחו מחדש מול היעד החדש.open STDOUT, ">", \$bufמנתב את כל הפלט הבא שלprint STDOUTלתוך$buf.מטפלי קובץ כ־Bareword (
open FH, ...) הם גלובלים של חבילה והם מושבתים תחתuse v5.36ואילך באמצעות התכונהbareword_filehandles. העדיפו סקלר לקסיקלי.שכבות ו־
${^OPEN}: כל שכבה מפורשת, אפילו:, משביתה את ברירות המחדל מהפראגמהopen. אם אתם מסתמכים על ברירת מחדל של פראגמה, השמיטו את הנקודתיים לחלוטין (<, לא<:).Pipe לפקודה עם מטה־תווים של shell: צורת ה־pipe בשני־ארגומנטים (
open $fh, "|cat -n | lpr") רצה דרך/bin/sh -c. צורת הרשימה בשלושה־ארגומנטים (open $fh, "|-", "cat", "-n") אינה, והיא ברירת המחדל הבטוחה יותר.מחרוזות סקלר בזיכרון: מטופלות כמחרוזות אוקטטים. ללא חיתוך, הסקלר אינו יכול להכיל נקודות קוד מעל
0xFF.סגירה אוטומטית ביציאת תחום: מטפל קובץ לקסיקלי נסגר כאשר ה־refcount שלו מגיע לאפס, אך הסגירה המובלעת אינה מדווחת על שגיאות. עבור קבצים שכתבתם אליהם, סגרו במפורש ובדקו את ערך ההחזרה.
openמולsysopen:openעוטף את הסמנטיקה שלfopen(3)עם שכבות PerlIO מעליה. עבור דגליopen(2)ישירים כמוO_EXCLאוO_NOFOLLOW, השתמשו ב־sysopen.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.
ראו גם#
close- שחרור מטפל קובץ; בדקו את ערך ההחזרה שלו עבור כתיבות שעברו בופרינג ופקודות pipesysopen- פתיחה עם דגליopen(2)גולמיים כשצריךO_EXCL,O_NOFOLLOW, או דיוק דומהbinmode- דחיפת או החלפת שכבות I/O על מטפל שכבר פתוחread- קריאות בייט בגודל קבוע מהמטפל ש־openהחזירreadline- קריאות רשומה־בכל־פעם (מה ש־<$fh>קורא)fileno- ה־file descriptor הבסיסי של ה־OS, עבורflock,select, אוfcntl