Tạo file tạm cho file rỗng tên ngẫu nhiên trong thư mục temporary của O.S. (Hệ điều hành). File này bị xóa tự động. Làm sao trong Ruby? Như sau:
require 'tempfile'
Tempfile.create { |f| f << "abc\n" }
f là file & << ghi vào. Built-in Ruby nên không cài gem. Ok. Đơn giản, nhưng vẫn có câu hỏi. Như: File xóa khi nào chính xác? Tại sao không đọc lại từ temp file? Tempfile có đảm bảo unique không? Tôi trả lời những câu này & thêm để bạn hiểu sâu!
Khác Biệt Giữa New & Create?
Chú ý Tempfile có hai method tạo file. new và create. Khác biệt? Theo doc, new tạo object Tempfile (như mong đợi), nhưng create cho object File. Tôi nghĩ không quan trọng, vì Tempfile delegate sang File. Khác biệt thực: create nhận block. new không. Thử: Tempfile.new {}. Cảnh báo hữu ích: # warning: Tempfile.new doesn't call the given block. Dùng block với create đảm bảo temp file xóa sau block kết thúc. Nảy sinh câu hỏi...
Khi Nào TempFile Bị Xóa?
Kiểm soát khi file xóa, tự xóa như file thường (delete), hoặc dùng create với block. Tự động xóa khi:
- Chương trình kết thúc
- File bị "garbage collected", nghĩa là xóa khỏi bộ nhớ bởi algorithm giải phóng không gian
t = Tempfile.new. Khi t out of scope, temp file có thể xóa. Linux có tool thú vị xem file tạo/xóa real-time: inotify-tools. Thử lệnh: inotifywait /tmp -m --format "%w %e %f %T" --timefmt "%H:%m:%S". Chạy Ruby code tạo file. Ví dụ: ruby -rtempfile -e "def c; t = Tempfile.new('testing'); end; c; sleep 10". Thấy: /tmp/ CREATE testing20190506-11391-1wqcng0 14:51:48
/tmp/ OPEN testing20190506-11391-1wqcng0 14:51:48
/tmp/ CLOSE_WRITE,CLOSE testing20190506-11391-1wqcng0 14:51:58
/tmp/ DELETE testing20190506-11391-1wqcng0 14:51:58
Tại Sao Không Đọc Lại Từ Temp File?
Thử đọc lại từ temp file nhận empty string. Ví dụ: Tempfile.create { |f| f << "abc\n"; f.read } # "". Tại sao? Files là object IO. IO object có con trỏ vị trí & khi ghi file vị trí này advance. Muốn đọc, phải rewind con trỏ. Như: Tempfile.create { |f| f << "abc\n"; f.rewind; f.read } # "abc\n". Cũng cần flush nội dung file. Ví dụ: temp = Tempfile.new; temp << "1"; temp << "2"; temp.flush.
Tempfiles Có Thực Sự Unique?
Tempfile tạo filename unique & set permission mode 600, nghĩa là chỉ user tạo file đọc được. Nhưng có bao giờ trùng tên? Doc nói:
"Phương pháp chọn filename Tempfile cả thread-safe và inter-process-safe: đảm bảo không thread/process nào khác chọn cùng filename."
Mô tả new cũng nói có thể raise error nếu không tìm unique filename. Cũng hay biết set prefix cho file. Như: Tempfile.new("banana-").path # "/tmp/banana-20190426-25403-1cm7sjt". Giảm khả năng collision tên.
Mở Tempfile Ở Binary Mode
Làm việc với ảnh, nhạc, hoặc bất kỳ thứ gì ngoài plain text, muốn set file mode binary. Binary mode ngăn chuyển đổi line-ending. Kết quả data "raw" hơn & tránh hỏng binary file. Binary mode KHÔNG enabled mặc định: temp = Tempfile.new; temp.binmode? # false. Bật: temp = Tempfile.new; temp.binmode; temp.binmode? # true. Cũng work với create: Tempfile.create do |f| f.binmode; f << "bacon\n" end.
Tóm Tắt
Bạn đã học temporary file Ruby dùng class Tempfile! Bây giờ lượt bạn practice. Cảm ơn bạn đã đọc 🙂