Mở file - text stream
Mở file trong Python sử dụng funtion open('ten_file'), mặc định ta sẽ mở file để đọc (read) ở dạng "text mode". Ta mặc định file cần mở là một file text (thường là .txt, .csv ...)>>> f = open('/etc/hosts')Ta đọc toàn bộ nội dung của file vào bộ nhớ bằng method read:
>>> print(f)
<_io .textiowrapper="" encoding="UTF-8" mode="r" name="/etc/hosts">
>>> content = f.read()Sau khi đọc đến cuối file (gặp ký tự EOF - end of file, một ký tự đặc biệt đánh dấu sự kết thúc của một file), nếu ta vẫn tiếp tục đọc, sẽ chỉ thu được empty string vì không còn gì để đọc.
>>> print(len(content))
918
>>> new = f.read()Bản chất file là một text stream, một dòng dữ liệu text. Python cho phép ta biết ta đang ở vị trí nào trong stream này với method tell
>>> print(new, len(new))
0
>>> help(f.tell)
Help on built-in function tell:
tell() method of _io.TextIOWrapper instance
Return current stream position.
>>> print(f.tell())
918
Ta đang ở cuối một file chứa 918 bytes, và đang ở vị trí 918. Để quay lại đầu file, thông thường ta có thể đóng file rồi mở lại để quay về đầu stream. Thế nhưng Python còn có method seek giúp di chuyển đến một vị trí bất kỳ trong stream, rất tiện để lên đầu hay xuống cuối
>>> help(f.seek)Có 3 vị trí khởi đầu seek method hỗ trợ:
Help on built-in function seek:
seek(cookie, whence=0, /) method of _io.TextIOWrapper instance
Change stream position.
Change the stream position to the given byte offset. The offset is
interpreted relative to the position indicated by whence. Values
for whence are:
* 0 -- start of stream (the default); offset should be zero or positive
* 1 -- current stream position; offset may be negative
* 2 -- end of stream; offset is usually negative
Return the new absolute position.
0: điểm bắt đầu của stream
1: điểm hiện tại của stream
2: điếm cuối của stream.
cookie hay offset là vị trí lệch đi so với điểm khởi đầu, rõ ràng nếu ta đang lấy điểm khởi đầu là đầu stream (0), offset phải là 0 hoặc số dương
>>> f.seek(0, 0) # về đầu file
>>> print(f.tell())
0
Còn khi ở cuối file, offset phải là 0 hoặc một số âm để chọn một vị trí trước vị trí cuối cùng
>>> f.seek(0, 2)Vì vậy, thay vì phải đóng file rồi mở lại để đọc từ đầu, chỉ cần dùng seek:
>>> print(f.tell())
918
>>> f.seek(0, 0)Để giúp code dễ đọc hơn, thay vì dùng các giá trị 0, 1, 2 cho whence, có thể dùng các hằng số có sẵn trong standard lib io
>>> data_again = f.read()
>>> print(data_again[:20])
127.0.0.1 localhos
>>> import io
>>> print(io.SEEK_SET, io.SEEK_CUR, io.SEEK_END)
0 1 2
Di chuyển trong binary file
>>> bf = open('/Users/hvn/Downloads/2015016-OdeToJoy-Beethoven-violin-solo.wav', 'rb')
>>> print(bf)
<_io .bufferedreader="" name="/Users/hvn/Downloads/2015016-OdeToJoy-Beethoven-violin-solo.wav">
>>> bf.seekable()
True
>>> print(bf.seek(0, io.SEEK_END))
1101342
>>> bf.tell()
1101342
>>> bf.seek(0, io.SEEK_SET)
>>> sound_data = bf.read()
>>> print(type(sound_data))
<class bytes="">
>>> len(sound_data)
1101342
Ta có thể sử dụng `seek` và `tell` giống như text file.
Ứng dụng
Viết một chương trình giả lập `tail -f` với những tính năng cao cấp hơn như xử lý logic của mỗi dòng trước khi in ra màn hình:import timeChạy câu lệnh sau trên terminal để ghi nối đuôi file /tmp/data_steam:
# Tạo file
fd = open('/tmp/data_stream', 'w').write('AAPL, 123, 0.5\nGOOG, 345, -0.2\n')
# Mở file rồi di chuyển xuống cuối
f = open('/tmp/data_stream')
f.seek(0, io.SEEK_END)
# Lặp vô hạn đọc các dòng mới
while True:
line = f.readline()
# Không có dòng nào mới, đọc tiếp từ file
if not line:
time.sleep(0.1)
continue
# Xử lý logic nếu có dòng mới trong file
name, price, change = line.split(',')
change = float(change)
if float(change) > 0:
print('Got {0:10s} {1:10s} {2:10f}'.format(name, price, change))
echo "PYMI, 456, 1.3" >> /tmp/data_streamTa sẽ thấy chương trình in ra:
Got PYMI 456 1.300000
Với đoạn code đơn giản trên, ta đã nhái lại được lệnh tail -f, lại thêm khả năng xử lý logic mà nếu với tail -f và các câu lệnh trên UNIX khác khá vất vả mới thực hiện được.
Xem bài gốc tại
https://github.com/pymivn/python-notes/blob/master/file_seek_tell.ipynb
Hết.
HVN at http://www.familug.org/ and http://pymi.vn
Đăng ký học lập trình #Python 3 từ con số 0 tại PyMI.vn - lớp Hà Nội khai giảng mùng 1 tháng 6, lớp Sài Gòn khai giảng đầu tháng 8. Xem chi tiết tại https://pymi.vn/ #PyMI #PyFML
No comments:
Post a Comment