Hướng dẫn python read bytes from file - python đọc byte từ tệp

Đọc tệp nhị phân trong Python và lặp qua từng byte

Mới trong Python 3.5 là mô -đun

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)
8, có phương pháp tiện lợi cụ thể để đọc trong một tệp dưới dạng byte, cho phép chúng tôi lặp lại các byte. Tôi coi đây là một câu trả lời tốt (nếu nhanh và bẩn):

import pathlib

for byte in pathlib.Path(path).read_bytes():
    print(byte)

Điều thú vị là đây là câu trả lời duy nhất để đề cập đến

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)
8.

Trong Python 2, có lẽ bạn sẽ làm điều này (như Vinay Sajip cũng gợi ý):

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)

Trong trường hợp tệp có thể quá lớn để lặp lại trong bộ nhớ, bạn sẽ chunk nó, một cách thành ngữ, sử dụng hàm

with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
0 với chữ ký
with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
1 - phiên bản Python 2:

with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)

(Một số câu trả lời khác đề cập đến điều này, nhưng một số ít cung cấp kích thước đọc hợp lý.)

Thực hành tốt nhất cho các tệp lớn hoặc đọc/đọc tương tác

Chúng ta hãy tạo một chức năng để thực hiện việc này, bao gồm sử dụng thành ngữ của thư viện tiêu chuẩn cho Python 3.5+:

from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk

Lưu ý rằng chúng tôi sử dụng

with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
2.
with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
3 khối cho đến khi nó nhận được tất cả các byte được yêu cầu hoặc
with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
4.
with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
2 cho phép chúng tôi tránh chặn, và nó có thể trở lại nhanh hơn vì điều này. Không có câu trả lời nào khác đề cập đến điều này là tốt.

Trình diễn sử dụng thực hành tốt nhất:

Hãy tạo một tệp với một megabyte (thực ra là mebiByte) của dữ liệu giả:

import random
import pathlib
path = 'pseudorandom_bytes'
pathobj = pathlib.Path(path)

pathobj.write_bytes(
  bytes(random.randint(0, 255) for _ in range(2**20)))

Bây giờ chúng ta hãy lặp lại nó và thành hiện thực nó trong bộ nhớ:

>>> l = list(file_byte_iterator(path))
>>> len(l)
1048576

Chúng tôi có thể kiểm tra bất kỳ phần nào của dữ liệu, ví dụ: 100 byte cuối cùng và 100 byte đầu tiên:

>>> l[-100:]
[208, 5, 156, 186, 58, 107, 24, 12, 75, 15, 1, 252, 216, 183, 235, 6, 136, 50, 222, 218, 7, 65, 234, 129, 240, 195, 165, 215, 245, 201, 222, 95, 87, 71, 232, 235, 36, 224, 190, 185, 12, 40, 131, 54, 79, 93, 210, 6, 154, 184, 82, 222, 80, 141, 117, 110, 254, 82, 29, 166, 91, 42, 232, 72, 231, 235, 33, 180, 238, 29, 61, 250, 38, 86, 120, 38, 49, 141, 17, 190, 191, 107, 95, 223, 222, 162, 116, 153, 232, 85, 100, 97, 41, 61, 219, 233, 237, 55, 246, 181]
>>> l[:100]
[28, 172, 79, 126, 36, 99, 103, 191, 146, 225, 24, 48, 113, 187, 48, 185, 31, 142, 216, 187, 27, 146, 215, 61, 111, 218, 171, 4, 160, 250, 110, 51, 128, 106, 3, 10, 116, 123, 128, 31, 73, 152, 58, 49, 184, 223, 17, 176, 166, 195, 6, 35, 206, 206, 39, 231, 89, 249, 21, 112, 168, 4, 88, 169, 215, 132, 255, 168, 129, 127, 60, 252, 244, 160, 80, 155, 246, 147, 234, 227, 157, 137, 101, 84, 115, 103, 77, 44, 84, 134, 140, 77, 224, 176, 242, 254, 171, 115, 193, 29]

Đừng lặp lại bằng các dòng cho các tệp nhị phân

Đừng làm như sau - điều này kéo một đoạn có kích thước tùy ý cho đến khi nó đến một ký tự mới - quá chậm khi các khối quá nhỏ, và có thể cũng quá lớn:

    with open(path, 'rb') as file:
        for chunk in file: # text newline iteration - not for bytes
            yield from chunk

Trên đây chỉ tốt cho các tệp văn bản có thể đọc được về mặt ngữ nghĩa của con người (như văn bản thuần túy, mã, đánh dấu, đánh dấu, v.v.

Đăng nhập vào tài khoản Python Barsels của bạn để lưu cài đặt screencast của bạn.

Vẫn chưa có tài khoản? Đăng ký tại đây.

Điều gì sẽ xảy ra nếu bạn muốn đọc từ một tệp không phải là một tệp văn bản?read from a file that isn't a text file?

Cách đọc tệp nhị phân trong Python

Nếu chúng ta cố gắng đọc một tệp zip bằng hàm

with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
7 tích hợp trong Python bằng chế độ đọc mặc định, chúng ta sẽ gặp lỗi:we'll get an error:

>>> with open("exercises.zip") as zip_file:
...     contents = zip_file.read()
...
Traceback (most recent call last):
  File "", line 2, in 
  File "/usr/lib/python3.10/codecs.py", line 322, in de
code
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8e in position 11: invalid sta
rt byte

Chúng tôi gặp lỗi vì các tệp zip không phải là tệp văn bản, chúng là các tệp nhị phân.binary files.

Để đọc từ một tệp nhị phân, chúng ta cần mở nó với chế độ

with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
8 thay vì chế độ mặc định của
with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
9:mode
with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
8 instead of the default mode of
with open(path, 'b') as file:
    callable = lambda: file.read(1024)
    sentinel = bytes() # or b''
    for chunk in iter(callable, sentinel): 
        for byte in chunk:
            print(byte)
9
:

>>> with open("exercises.zip", mode="rb") as zip_file:
...     contents = zip_file.read()
...

Khi bạn đọc từ một tệp nhị phân, bạn sẽ không lấy lại chuỗi. Bạn sẽ nhận lại một đối tượng

from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
0, còn được gọi là chuỗi byte:byte string:

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)
0

Chuỗi byte không có ký tự trong đó: họ có byte trong đó.: they have bytes in them.

Các byte trong một tập tin sẽ không giúp chúng tôi rất nhiều trừ khi chúng tôi hiểu ý nghĩa của chúng.

Sử dụng thư viện để đọc tệp nhị phân của bạn

Bạn có thể sẽ không đọc một tập tin nhị phân rất thường xuyên.

Khi làm việc với các tệp nhị phân, bạn thường sử dụng thư viện (thư viện Python tích hợp hoặc thư viện của bên thứ ba) biết cách xử lý loại tệp cụ thể mà bạn đang làm việc. Thư viện đó sẽ thực hiện công việc giải mã các byte từ tệp của bạn thành một cái gì đó dễ làm việc hơn.

Ví dụ: mô -đun

from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
1 của Python có thể giúp chúng tôi đọc dữ liệu trong tệp zip:

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)
1

Tốt nhất là tránh thực hiện logic kiểm tra byte hoặc kiểm tra byte của riêng bạn nếu ai đó đã thực hiện công việc đó cho bạn.avoid implementing your own byte-checking or byte manipulation logic if someone has already done that work for you.

Làm việc ở cấp độ byte trong Python

Đôi khi bạn sẽ làm việc với thư viện hoặc API yêu cầu bạn phải làm việc trực tiếp ở cấp độ byte. Trong trường hợp đó, bạn sẽ muốn có ít nhất một chút quen thuộc với các tệp nhị phân và chuỗi byte.

Ví dụ: giả sử chúng tôi muốn tính toán

from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
2
from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
3 của một tệp đã cho.

Ở đây chúng tôi có một chức năng gọi là

from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
4 làm điều đó:

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)
2

Hàm này đọc tất cả các dữ liệu nhị phân trong tệp này. Chúng tôi đang đọc byte vì mô -đun

from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
5 của Python yêu cầu chúng tôi làm việc với các byte. Mô-đun
from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
5 hoạt động ở cấp độ thấp: nó hoạt động với
from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
0 thay vì với các chuỗi.

Vì vậy, chúng tôi sẽ chuyển tất cả các byte trong tệp của chúng tôi để có một đối tượng băm và sau đó gọi phương thức

from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
8 trên đối tượng băm đó để có được một chuỗi các ký tự thập lục phân đại diện cho tổng kiểm tra SHA-256 của tệp này:

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)
3

Chức năng này hoạt động tốt, nhưng đọc các tệp rất lớn với chức năng này có thể là một vấn đề.

Đọc các tệp nhị phân trong các khối

Hàm

from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
4 của chúng tôi đọc toàn bộ tệp vào bộ nhớ cùng một lúc. Với một tập tin thực sự lớn có thể chiếm rất nhiều bộ nhớ.the whole file into memory all at once. With a really big file that might take up a lot of memory.

Với một tệp văn bản, cách thông thường để giải quyết vấn đề này sẽ là đọc từng dòng tệp. Nhưng các tập tin nhị phân không nhất thiết phải có dòng! Thay vào đó, chúng ta có thể cố gắng đọc Chunk của Chunk.binary files don't necessarily have lines! Instead, we could try to read chunk by chunk.

Đầu tiên chúng tôi sẽ đọc một đoạn tám kilobyte từ tập tin của chúng tôi:

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)
4

Chúng tôi tạo một đối tượng băm mới trước và sau đó đọc một đoạn tám kilobyte (bằng cách chuyển số byte cho phương thức

import random
import pathlib
path = 'pseudorandom_bytes'
pathobj = pathlib.Path(path)

pathobj.write_bytes(
  bytes(random.randint(0, 255) for _ in range(2**20)))
0 của đối tượng tệp của chúng tôi).

Bây giờ chúng tôi cần phần còn lại của các phần của tập tin của chúng tôi. Vì vậy, chúng tôi sẽ lặp:

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)
5

Chúng tôi liên tục đọc một đoạn, cập nhật đối tượng băm của chúng tôi, và sau đó đọc một đoạn khác.

Miễn là chúng tôi không ở cuối tập tin của chúng tôi, chúng tôi sẽ lấy lại một sự thật khi chúng tôi đọc.

Nhưng khi chúng tôi đọc ở cuối tệp của chúng tôi, chúng tôi sẽ lấy lại một chuỗi byte trống. Chuỗi byte trống (như chuỗi trống) là giả, vì vậy ở cuối tập tin của chúng tôi, chúng tôi sẽ thoát ra khỏi vòng lặp của chúng tôi. Sau đó, chúng tôi sẽ trả lại

from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
8 giống như chúng tôi đã làm trước đây.

Hàm

from pathlib import Path
from functools import partial
from io import DEFAULT_BUFFER_SIZE

def file_byte_iterator(path):
    """given a path, return an iterator over the file
    that lazily loads the file
    """
    path = Path(path)
    with path.open('rb') as file:
        reader = partial(file.read1, DEFAULT_BUFFER_SIZE)
        file_iterator = iter(reader, bytes())
        for chunk in file_iterator:
            yield from chunk
4 đã được sửa đổi này hoạt động như trước:

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)
6

Nhưng thay vì đọc toàn bộ tệp của chúng tôi vào bộ nhớ, giờ đây chúng tôi đang đọc tệp chunk-by-chunk của chúng tôi.reading our file chunk-by-chunk.

Bên cạnh: sử dụng biểu thức gán

Thông thường để xem biểu thức gán được sử dụng (thông qua toán tử Walrus của Python) khi đọc các tệp chunk-by-chunk:assignment expression used (via Python's walrus operator) when reading files chunk-by-chunk:

with open(path, 'b') as file:
    for byte in file.read():
        print(byte)
7

Việc đọc dữ liệu liên tục trong vòng lặp

import random
import pathlib
path = 'pseudorandom_bytes'
pathobj = pathlib.Path(path)

pathobj.write_bytes(
  bytes(random.randint(0, 255) for _ in range(2**20)))
3 là một trường hợp sử dụng khá tốt cho biểu thức gán. Nó có thể trông hơi kỳ lạ, nhưng nó tiết kiệm cho chúng ta một vài dòng mã.it does save us a few lines of code.

Người vận hành Walrus đã được thêm vào trong Python 3,8.

Bản tóm tắt

Khi bạn đọc một tệp nhị phân trong Python, bạn sẽ nhận lại byte.you'll get back bytes.

Khi bạn đang đọc một tệp nhị phân lớn, có lẽ bạn sẽ muốn đọc nó theo chunk.read it chunk-by-chunk.

Nhưng tốt nhất là tránh tự đọc các tệp nhị phân nếu bạn có thể. Nếu có thư viện của bên thứ ba có thể giúp bạn xử lý tệp nhị phân của mình, có lẽ bạn nên sử dụng thư viện đó để thực hiện xử lý dựa trên byte cho bạn.avoid reading binary files yourself if you can. If there's a third-party library that can help you process your binary file, you should probably use that library to do the byte-based processing for you.

Làm cách nào để đọc một tệp nhị phân trong Python?

Hàm Open () mở một tệp ở định dạng văn bản theo mặc định. Để mở một tệp ở định dạng nhị phân, thêm 'B' vào tham số chế độ. Do đó, chế độ "RB" mở tệp ở định dạng nhị phân để đọc, trong khi chế độ "WB" mở tệp ở định dạng nhị phân để viết. Không giống như các tệp văn bản, các tệp nhị phân không thể đọc được của con người.add 'b' to the mode parameter. Hence the "rb" mode opens the file in binary format for reading, while the "wb" mode opens the file in binary format for writing. Unlike text files, binary files are not human-readable.

Làm thế nào để bạn tải byte trong Python?

Hàm Python Byte () chuyển đổi một đối tượng thành đối tượng đại diện byte bất biến của kích thước và dữ liệu đã cho ...
Cú pháp: Byte (SRC, ENC, ERR).
Thông số :.
Trả về: Đối tượng bất biến byte bao gồm các ký tự unicode 0-256 theo loại SRC ..

Đọc () trở lại trong Python là gì?

Định nghĩa và cách sử dụng.Phương thức Read () trả về số byte được chỉ định từ tệp.Mặc định là -1 có nghĩa là toàn bộ tệp.the specified number of bytes from the file. Default is -1 which means the whole file.

Làm cách nào để đọc toàn bộ tệp trong Python?

Text = f.Read () (có thể thử những thứ này trong >>> phiên dịch, chạy python3 trong một thư mục có tệp văn bản trong đó chúng ta có thể đọc, chẳng hạn như thư mục "WordCount".) Đọc toàn bộ tệp thành 1 chuỗi - ít mã hơn và ít bận tâmhơn đi từng dòng.....
dòng = f.Readlines () f.Readlines () Trả về một danh sách các chuỗi, 1 cho mỗi dòng ..