Работа с бинарными данными файлов в Python: от основ до продвинутых техник

Раздел: Работа с файлами -> Файловый ввод-вывод

Работа с байтами файла в Python

Как эффективно читать большие бинарные файлы не загружая их целиком в память?

Наиболее производительный способ для работы с байтами файла - чтение порциями (chunks) с использованием буфера. Это позволяет обрабатывать файлы любого размера, контролируя потребление оперативной памяти.


with open('data.bin', 'rb') as f:
    chunk_size = 4096  # 4 КБ
    while True:
        chunk = f.read(chunk_size)
        if not chunk:
            break
        # Обработка байтов chunk
        print(f'Прочитано {len(chunk)} байт')
  

ввод программ на python (ввод данных в программе python)

В данном примере файл открывается в бинарном режиме чтения ('rb'). Метод read(chunk_size) возвращает объект bytes длиной не более chunk_size. Цикл продолжается пока не будет получен пустой фрагмент, что сигнализирует о конце файла. Рекомендуется выбирать размер chunk_size кратным размеру дискового блока (обычно 4096 или 65536 байт).

Типичные ошибки

  • Забыть указать режим 'b' в параметре mode - тогда read будет возвращать строку, а не байты, что приведёт к ошибке при попытке обработать бинарные данные.
  • Игнорирование закрытия файла - использование блока with гарантирует освобождение ресурсов.
  • Неправильный размер буфера: слишком малый chunk_size приводит к частым обращениям к диску, слишком большой - к избыточному потреблению памяти.

Как прочитать весь файл в память в виде байтов?

Для небольших файлов удобно загрузить содержимое целиком. Это упрощает код и позволяет выполнять операции над всеми байтами сразу.


with open('image.png', 'rb') as f:
    data = f.read()
print(f'Размер файла: {len(data)} байт')
  

Python file io (ввод-вывод файлов в python)

Проблемы

  • При попытке прочитать большой файл (несколько гигабайт) может не хватить оперативной памяти, программа аварийно завершится.
  • Метод read() без аргументов читает до конца файла; для бинарного потока это корректно, но для текстовых нужно учитывать кодировку.

Как записать байты в файл?

Для записи бинарных данных используется режим 'wb' или 'ab' (дозапись).


with open('output.bin', 'wb') as f:
    f.write(b'\x48\x65\x6C\x6C\x6F')  # Hello
  

Python temp files (временные файлы в python)

Важно передавать именно объект bytes или bytearray, а не строку. Попытка записать строку приведёт к ошибке TypeError: a bytes-like object is required, not 'str'.

Типичные ошибки

  • Смешение бинарного и текстового режимов: если открыть файл в текстовом режиме и попытаться записать байты, будет ошибка.
  • Забыть закрыть файл - данные могут не записаться полностью.
  • Использование неправильного метода: writelines ожидает список строк, а не байтов.

Как перемещаться по файлу с помощью seek и tell?

Для произвольного доступа к байтам используются методы seek(offset, whence) и tell(). Это полезно при чтении бинарных форматов с фиксированной структурой.


with open('file.bin', 'rb') as f:
    f.seek(100, 0)  # Переместиться на 100 байт от начала
    data = f.read(16)  # Прочитать 16 байт
    print(f'Текущая позиция: {f.tell()}')
  

Python index files (индексация файлов в python)

Значения whence: 0 - от начала файла, 1 - от текущей позиции, 2 - от конца файла. При whence=2 offset обычно отрицательный.

Возможные проблемы

  • Попытка seek за пределами файла - в зависимости от системы может расширить файл (при записи) или вызвать исключение.
  • Несоответствие смещения границам записи данных - например, чтение целого числа со смещением не кратным его размеру.

Как изменять байты в файле без перезаписи всего файла?

Режим 'r+b' позволяет одновременно читать и записывать, используя seek для позиционирования.


with open('data.bin', 'r+b') as f:
    f.seek(10)
    f.write(b'\xAA\xBB')  # Замена 2 байт на позиции 10
  

File python class (класс для работы с файлами в python)

Внимание

  • Запись в произвольное место может повредить существующие данные, если новый фрагмент короче или длиннее заменяемой области. Для точной замены нужно заранее знать структуру.
  • Неверное использование writelines или смешение с текстовым режимом.

Как работать с байтами в памяти без файла?

Модуль io предоставляет класс BytesIO для работы с байтами как с файловым объектом. Это удобно для тестирования, сжатия или преобразований.


from io import BytesIO

buf = BytesIO()
buf.write(b'Hello')
buf.write(b' World')
buf.seek(0)
data = buf.read()
print(data)  # b'Hello World'
  

Ошибки

  • Попытка записать строку без кодирования аналогична файловому потоку.
  • Необходимость сброса позиции перед чтением после записи.
- Python copy file (копирование файла в python)
- Python log file (логирование в файл в python)
- Python file methods (методы работы с файлами в python)

Продвинутые примеры работы с байтами файлов

Чтение магического числа файла

Многие форматы (PNG, PDF) имеют сигнатуру - первые несколько байт. Следующий код проверяет, является ли файл PNG.

Пример

import os

filename = 'example.png'
with open(filename, 'rb') as f:
    magic = f.read(8)

if magic == b'\x89PNG\r\n\x1a\n':
    print('Это PNG файл')
else:
    print('Неизвестный формат')
Это PNG файл

Использование struct для упаковки и распаковки бинарных данных

Модуль struct позволяет сериализовать целые числа, числа с плавающей точкой и строки фиксированной длины в байтовые последовательности и обратно. Пример записи и чтения заголовка с 32-битным целым и 64-битным числом.

Пример

import struct

# Запись
with open('struct.bin', 'wb') as f:
    packed = struct.pack('<I d', 42, 3.14)  # little-endian, 4 + 8 байт
    f.write(packed)

# Чтение
with open('struct.bin', 'rb') as f:
    data = f.read(12)
    integer, double = struct.unpack('<I d', data)
    print(integer, double)
42 3.14

Эффективное копирование и изменение байтов с memoryview

Класс memoryview позволяет работать с буферами без создания копий. Это ускоряет операции над большими массивами байтов.

Пример

with open('large.bin', 'rb') as f:
    data = bytearray(f.read(1024))
view = memoryview(data)
view[:5] = b'ABCDE'  # Изменение первых 5 байт без копирования
print(data[:10])
bytearray(b'ABCDE...')

Отображение файла в память с помощью mmap

Модуль mmap позволяет работать с файлом как с массивом байтов, используя виртуальную память. Это даёт высокую производительность для произвольного доступа.

Пример

import mmap

with open('data.bin', 'r+b') as f:
    with mmap.mmap(f.fileno(), 0) as mm:
        # Чтение первых 10 байт
        print(mm[:10])
        # Замена байтов
        mm[5:8] = b'XYZ'
b'... (первые 10 байт) ...'

Асинхронное чтение байтов с aiofiles

Для неблокирующей работы с файлами в асинхронных приложениях используется библиотека aiofiles.

Пример

import asyncio
import aiofiles

async def read_bytes():
    async with aiofiles.open('bigfile.bin', 'rb') as f:
        chunk = await f.read(1024)
        print(f'Асинхронно прочитано {len(chunk)} байт')

asyncio.run(read_bytes())
Асинхронно прочитано 1024 байт

Чтение бинарного файла в массив чисел numpy

Для научных расчётов бинарные данные часто загружаются в numpy массивы. Пример чтения 32-битных float из файла.

Пример

import numpy as np

with open('floats.bin', 'rb') as f:
    data = np.fromfile(f, dtype=np.float32)
print(data[:5])
[ 1.5  2.3  ... ]

Байты файла Python - comments

En
Python file bytes (python)