Các lệnh vào/ra tệp:

Một phần của tài liệu Phân tích Cấu trúc chương trình Perl, các kiểu dữ liệu và các thao tác trên dữ liệu (Trang 46)

3.1 Tước hiệu tệp

Tước hiệu tệp là tên trong một chương trình Perl dành cho việc nối giữa tiến trình Perl của bạn và bên ngoài. Chúng ta đã thấy và dùng tước hiệu tệp một cách không tường minh: STDIN là một tước hiệu tệp, đặt tên cho việc nối giữa tiến trình Perl và lối vào chuẩn của UNIX. Giống như vậy, Perl cung cấp STDOUT (cho lối ra chuẩn) và STDERR (cho lối ra chuẩn cho lỗi). Những tên này là trùng với các tên được dùng trong bộ trình thư viện "vào/ra chuẩn" của UNIX, Perl dùng chúng cho hầu hết việc vào/ra.

Tên tước hiệu tệp cũng giống như tên dành cho các khối có nhãn, nhưng chúng đến từ một không gian tên khác (cho nên bạn có thể có một vô hướng $jerry, một mảng @jerry, một mảng băm %jerry, một chương trình con jerry(), một nhãn jerry:, và bây giờ một tước hiệu tệp jerry). Giống như nhãn khối, tước hiệu tệp được dùng không cần một kí tự đặc biệt đứng trước, và do vậy có thể bị lẫn lộn với các từ dành riêng hiện có hay trong tương lai. Một lần nữa, khuyến cáo của Larry là bạn hãy dùng tất cả các chữ hoa trong tước hiệu tệp của mình - không chỉ nó biểu thị tốt hơn, mà nó cũng sẽ đảm bảo rằng chương trình của bạn sẽ không hỏng khi các từ dành riêng tương lai được đưa vào.

3.2 Mở và đóng một tước hiệu tệp

Perl cung cấp ba tước hiệu tệp STDIN, STDOUT, STDERR mà tự động mở cho các tệp hay thiết bị do tiến trình cha mẹ của chương trình này đã thiết lập. Bạn dùng toán tử open() để mở các tước hiệu tệp phụ, hệt như bạn làm trong chương trình được viết trong C. Cú pháp của nó giống thế này:

open(FILEHANDLE, "ten file");

với FILEHANDLE là tước hiệu tệp mới, còn ten file là tên tệp ngoài (như một tệp hay thiết bị) mà sẽ được liên kết với tước hiệu tệp mới. Việc gọi này mở tước hiệu tệp để đọc. Việc mở một tệp để ghi thì cũng dùng cùng toán tử open, nhưng phần tiền tố của tên tệp có một dấu lớn hơn (>):

open(OUT, ">outfile");

Chúng ta sẽ thấy trong mục "Dùng tước hiệu tệp" dưới đây cách sử dụng tước hiệu tệp này. Cũng tương tự như vậy, bạn có thể mở một tệp để thêm vào sau bằng việc dùng hai dấu lớn hơn làm tiền tố (>>), ví dụ như:

open(LOGFILE, ">>mylogfile");

Tất cả ba dạng này của open trả về giá trị đúng (true) nếu việc mở thành công và sai (false) nếu thất bại. (Việc mở một tệp để đọc sẽ sai nếu như tệp đó không tồn tại hay không thể truy cập được bởi không được phép của hệ điều hàng; việc mở tệp để ghi sẽ sai nếu ta không được phép ghi vào tệp hay thư mục).

Khi bạn kết thúc với một tước hiệu tệp, bạn có thể đóng nó bằng toán tử close, tựa như: close(LOGFILE);

Việc mở lại một tước hiệu tệp cũng làm đóng tệp mở trước đó một cách tự động, cũng như khi ra khỏi chương trình. Vì điều này, phần lớn các chương trình Perl không bận tâm với close. Nhưng nó vẫn có đó nếu bạn muốn được chặt chẽ hay chắc chắn rằng tất cả dữ liệu đều được đẩy ra hết đôi khi sớm hơn việc kết thúc của chương trình.

3.3 die()

Ta hãy coi đây như là một chú thích lớn cuối trang, nhưng lại nằm ở giữa trang.

Một tước hiệu tệp mà không được mở thành công thì có thể vẫn được dùng mà thậm chí không gây ra cảnh báo gì nhiều lắm trong toàn bộ chương trình. Nếu bạn đọc từ tước hiệu tệp thì bạn sẽ nhận được ngay cuối tệp. Nếu bạn ghi lên tước hiệu tệp thì dữ liệu bị bỏ đi.

Thường bạn muốn kiểm tra lại kết quả của việc mở tệp và báo cáo lại lỗi nếu kết quả không phải là điều bạn dự kiến. Chắc chắn, bạn có thể rải rắc trong chương trình của mình với những thứ kiểu như:

unless (open(DATAPLACE, ">/tmp/dataplace")) { print "Co loi: khong the tao duoc tep /tmp/dataplace\n"; } else {

# phan con lai cua chuong trinh }

Nhưng bạn sẽ phải làm nhiều việc lắm. Và điều thường xẩy ra với Perl là đưa ra một lối tắt. Toán tử die() lấy một danh sách bên trong dấu ngoặc tròn tuỳ chọn, đưa ra danh sách đó (giống như print) trên lối ra lỗi chuẩn, và rồi kết thúc tiến trình Perl (tiến trình đang chạy chương trình Perl) với một trạng thái ra khác không của UNIX (nói chung

chỉ ra một cái gì đó bất thường xẩy ra). Cho nên, viết lại đoạn mã trên thì ta sẽ thấy nó giống như thế này:

unless (open(DATAPLACE, ">/tmp/dataplace")) { die "Co loi: khong the tao duoc tep /tmp/dataplace\n"; }

# phan con lai cua chuong trinh

Nhưng chúng ta thậm chí còn có thể đi thêm một bước nữa. Nhớ rằng ta có thể dùng toán tử logic hoặc (||) để làm ngắn thêm điều này, như trong ví dụ sau:

unless (open(DATAPLACE, ">/tmp/dataplace")) || die "Co loi, khong the tao duoc tep /tmp/dataplace\n";

Vậy die sẽ được thực hiện chỉ khi kết quả của open là sai. Cách thông dụng để đọc hiểu câu lệnh trên là "hãy mở tệp đó ra hoặc die" và đó là cách dễ dàng để nhớ bất kì khi nào dùng toán tử logic và (&&) hay logic hoặc (||).

Thông báo được in ra từ die (được xây dựng từ đối của die) có tên chương trình Perl và số dòng được gắn tự động vào, cho nên bạn có thể dễ dàng xác định được die nào trong chương trình của bạn đã in ra thông báo lỗi này. Nếu bạn không thích số dòng hay tên tệp bị lộ ra, bạn phải thêm một dấu xuống dòng vào cuối thông báo. Chẳng hạn:

die "...";

sẽ in ra tên tệp và số dòng, trong khi: die "....\n";

thì không in ra tên tệp và số dòng.

Một khi tước hiệu tệp được mở ra để đọc thì bạn có thể đọc các dòng từ nó hệt như bạn có thể đọc từ lối vào chuẩn với STDIN. Vậy, chẳng hạn, để đọc các dòng từ tệp mật mã: (adsbygoogle = window.adsbygoogle || []).push({});

open (EP, "/etc/passwd"); while (<EP>) {

chop;

print "Tim thay $_ trong tep /etc/passwd!\n"; }

Lưu ý rằng tước hiệu tệp mới mở được dùng bên trong dấu ngoặc nhọn hệt như ta đã dùng STDIN trước đây.

Một tước hiệu tệp mở ra để ghi hay hiệu đính đều phải được cho như một đối của toán tử print, xuất hiện ngay sau từ khoá print nhưng trước danh sách đối khác. Ví dụ: print LOGFILE "Tong so = $total\n";

print STDOUT "Xin chao!\n"; # tuong tu nhu print "Xin chap!\n";

Trong trường hợp này, thông báo bắt đầu với "Tong so = $total\n" ghi lên tước hiệu tệp LOGFILE, mà giả thiết là đã mở trước đây trong chương trình. Và cau "Xin chao!\n" sẽ đi ra lối ra chuẩn, hệt như khi bạn không xác định tước hiệu tệp. Chúng ta nói rằng STDOUT là tước hiệu xử lí tệp ngầm định cho câu lệnh print.

Vậy, tóm lại, sau đây là cách để sao chép tất cả văn bản từ một tệp được xác định trong $a vào một tệp được xác định trong $b. Nó minh hoạ gần như mọi thứ mà ta đã học trong chương này vừa qua:

open (IN, $a) || die "Khong the mo duoc $a de doc"; open (OUT, ">$b") || die "Khong the mo duoc $b de ghi"; while (<IN>) { #Doc 1 dong tu tep $a vao $_

print OUT $_; #In dong do vao tep $b }

close(IN); close(OUT);

Một phần của tài liệu Phân tích Cấu trúc chương trình Perl, các kiểu dữ liệu và các thao tác trên dữ liệu (Trang 46)