Python. Бинарные файлы. Примеры работы с бинарными файлами




Бинарные файлы. Примеры работы с бинарными файлами

В данной теме показано как можно сохранять данные в бинарных файлах без использования стандартных средств pickle или struct языка Python.


Содержание


Поиск на других ресурсах:

1. Понятие о бинарных файлах. Представление информации в бинарных файлах

В языке Python существуют средства для работы с бинарными или двоичными файлами. Бинарные файлы используют строки типа bytes. Это значит при чтении бинарных данных из файла возвращается объект типа bytes.

Открытие бинарного файла осуществляется с помощью функции open(), параметр mode которой содержит символ ‘b’. Более подробно об открытии/закрытии бинарных файлов описывается здесь.

В отличие от текстовых, бинарные файлы не выполняют преобразования символов конца строки ‘\n’.

Пример, демонстрирующий особенности представления информации в бинарных файлах.

# Python. Работа с бинарными файлами

# Открыть бинарный файл для чтения
f = open('myfile1.bin', 'rb')

# Получить одну строку из бинарного файла
d = f.read()

# Вывести эту строку.
# Будет получен вывод в виде строки символов
print("d = ", d) # d = b'\x80\x03]q\x00(K\x01\x88G@\x07\n=p\xa3\xd7\ne.'

# Если вывести как отдельный символ,
# то будет выведен код символа - как целое число
print("d[5] = ", d[5]) # d[5] =   40
print("d[0] = ", d[0]) # d[0] =   128

# Использовать функцию bin для отдельного символа
print(bin(d[2])) # 0b1011101
f.close()

Результат работы программы

d =   b'\x80\x03]q\x00(K\x01\x88G@\x07\n=p\xa3\xd7\ne.'
d[5] = 40
d[0] = 128
0b1011101

На основании примера выше можно сделать следующие выводы:

  • строка бинарных данных выводится как строка;
  • отдельный символ (элемент) бинарных данных представлен в виде 8-битных целых чисел.

 

2. Запись/чтение списка, который содержит вещественные числа. Пример

 

# Бинарные файлы. Запись/чтение списка вещественных чисел
# 1. Заданный список вещественных чисел
L = [1.5, 2.8, 3.3]

# 2. Запись файла
# 2.1. Открыть файл для записи
f = open('myfile3.bin', 'wb')

# 2.2. Обход списка и запись данных в файл
for item in L:
    # добавить символ '\n', чтобы можно было распознать числа
    s = str(item) + '\n'

    # Метод encode() - конвертирует строку в последовательность байт
    bt = s.encode()
    f.write(bt) # метод write() - запись в файл

# 2.3. Закрыть файл
f.close();

# 3. Считать список из бинарного файла 'myfile3.bin'
# 3.1. Создать пустой список
L2 = []

# 3.2. Открыть файл для чтения
f = open('myfile3.bin', 'rb')

# 3.3. Обход строк файла, конвертирование и добавление в список L2
for ln in f:
    x = float(ln) # взять число
    L2 = L2 + [x] # Добавить число к списку

# 3.4. Вывести список
print("L2 = ", L2) # L2 = [1.5, 2.8, 3.3]

# 3.5. Закрыть файл
f.close();

Результат работы программы

L2 = [1.5, 2.8, 3.3]

 

3. Запись/чтение кортежа, содержащего строки символов. Пример

В данном примере строки символов в бинарном файле разделяются символом ‘\n’. Таким образом, можно записывать и читать информацию без потери ее структуры.

# Бинарные файлы. Запись/чтение кортежа, содержащего строки символов

# 1. Заданный кортеж со строками
T = ( 'abc', 'def', 'ghi', 'jk lmn')

# 2. Запись кортежа T в файл 'myfile5.bin'
# 2.1. Открыть файл для записи
f = open('myfile5.bin', 'wb')

# 2.2. Цикл обхода кортежа
for item in T:
    bt = (item + '\n').encode() # конвертировать (str + '\n') => bytes
    f.write(bt) # записать bt в файл

# 2.3. Закрыть файл
f.close();

# 3. Считать кортеж из бинарного файла 'myfile5.bin'
# 3.1. Открыть файл для чтения
f = open('myfile5.bin', 'rb')

# 3.2. Новый кортеж
T2 = ()

# 3.3. Прочитать данные из файла
for line in f:
    s = line.decode() # конвертировать bytes=>str
    s = s[:-1] # Убрать последний символ
    T2 = T2 + (s,) # Добавить строку s к кортежу

# 3.4. Вывести кортеж
print("T2 = ", T2)

# 3.5. Закрыть файл
f.close();

Результат работы программы

T2 = ('abc', 'def', 'ghi', 'jk lmn')

 



4. Запись/чтение множества, содержащего вещественные числа. Пример

Множество, которое содержит только однотипные объекты можно записать в файл. В данном примере записывается множество вещественных чисел.

# Бинарные файлы. Запись/чтение множества,
# которое содержит вещественные числа

# 1. Заданное множество
M = { 0.2, 0.3, 0.8, 1.2, 1.77 }

# 2. Запись множества M в файл 'myfile6.bin'
# 2.1. Открыть файл для записи
f = open('myfile6.bin', 'wb')

# 2.2. Цикл обхода множества
for item in M:
    s = str(item) + '\n' # конвертировать float=>str + '\n'
    bt = s.encode()     # конвертировать str=>bytes
    f.write(bt)         # записать bt в файл

# 2.3. Закрыть файл
f.close();

# 3. Считать множество из бинарного файла 'myfile6.bin'
# 3.1. Открыть файл для чтения
f = open('myfile6.bin', 'rb')

# 3.2. Новое множество
M2 = set()

# 3.3. Прочитать данные из файла
for line in f:
    x = float(line) # конвертировать bytes=>x
    M2 = M2.union({x}) # Добавить x к множеству

# 3.4. Вывести множество
print("M2 = ", M2)

# 3.5. Закрыть файл
f.close()

Результат работы программы

M2 = {0.2, 0.8, 0.3, 1.77, 1.2}

Вид файла myfile6.bin

0.2
0.8
1.77
0.3
1.2

 

5. Запись/чтение двумерной матрицы строк заданного размера. Пример

В примере матрица представлена в виде списка.

# Бинарные файлы. Запись/чтение матрицы, которая содержит строки

# 1. Заданная матрица строк размером 3*4
MATRIX = [ [ 'aa', 'ab', 'ac', 'ad'],
           [ 'ba', 'bb', 'bc', 'bd'],
           [ 'ca', 'cb', 'cc', 'cd'] ]

# 2. Запись матрицы MATRIX в файл 'myfile7.bin'
# 2.1. Открыть файл для записи
f = open('myfile7.bin', 'wb')

# 2.2. Сначала записать размер матрицы
m = 3
n = 4

# конвертировать m, n в строчный тип str
sm = str(m) + '\n'
sn = str(n) + '\n'

# конвертировать строку str в bytes
bm = sm.encode()
bn = sn.encode()

# записать размеры матрицы в файл
f.write(bm)
f.write(bn)

# 2.3. Цикл обхода матрицы
for row in MATRIX:
    # здесь нужно просто записать строки с символом '\n'
    for item in row:
        item = item + '\n'
        bt = item.encode() # str=>bytes
        f.write(bt)       # записать bt в файл

# 2.3. Закрыть файл
f.close();

# 3. Считать матрицу из бинарного файла 'myfile7.bin'
# 3.1. Открыть файл для чтения
f = open('myfile7.bin', 'rb')

# 3.2. Новая матрица
MATRIX2 = []

# 3.3. Прочитать данные из файла
# 3.3.1. Сначала прочитать размер
s = f.readline()
m2 = int(s)
s = f.readline()
n2 = int(s)

# 3.3.2. Цикл чтения строк и создание матрицы размером m2*n2
i = 0
while i < m2:   # m2 строк в матрице
    row = [] # одна строка списка
    j = 0
    while j < n2:
        bs = f.readline() # прочитать один элемент типа bytes
        s = bs.decode() # конвертировать bytes=>str
        s = s[:-1] # убрать '\n'
        row += [s]   # добавить к списку
        j = j+1

    MATRIX2 += [row] # добавить одну строку списка к матрице
    i = i+1

# 3.4. Вывести новую матрицу
i = 0
while i < m2:
    print("MATRIX2[", i, "] = ", MATRIX2[i])
    i = i+1

# 3.5. Закрыть файл
f.close()

Результат работы программы

MATRIX2[ 0 ] = ['aa', 'ab', 'ac', 'ad']
MATRIX2[ 1 ] = ['ba', 'bb', 'bc', 'bd']
MATRIX2[ 2 ] = ['ca', 'cb', 'cc', 'cd']

Вид файла myfile7.txt

3
4
aa
ab
ac
ad
ba
bb
bc
bd
ca
cb
cc
cd

 

6. Запись/чтение словаря. Пример

Пусть задан некоторый словарь, который нужно записать в бинарный файл.

# Бинарные файлы. Запись/чтение словаря
# 1. Заданный словарь. Пары типа str:int
D = { 'One':1, 'Two':2, 'Three':3, 'Four':4 }

# 2. Запись словаря D в файл 'myfile8.bin'
# 2.1. Открыть файл для записи
f = open('myfile8.bin', 'wb')

for key in D: # обход словаря
    # взять значение value
    value = D[key]

    # Записать последовательно key, затем value
    svalue = str(value) + '\n' # сначала конвертировать value в строку
    skey = key + '\n' # к строке key добавить '\n'

    # Конвертировать key:svalue из строки в bytes
    b_key = skey.encode()
    b_svalue = svalue.encode()

    # записать b_key, b_svalue в файл
    f.write(b_key)
    f.write(b_svalue)

# 2.3. Закрыть файл
f.close();

# 3. Считать словарь из бинарного файла 'myfile8.bin'
# 3.1. Открыть файл для чтения
f = open('myfile8.bin', 'rb')

# 3.2. Новый словарь, который будет прочитан из файла
D2 = dict()

# 3.3. Прочитать весь файл сразу
b_strings = f.readlines() # b_strings - список строк типа bytes

# 3.4. Обойти список b_strings.
#     Сначала читается ключ, затем значение и т.д.
fkey = True # если True, то читается ключ, иначе читается значение
for item in b_strings:
    if fkey: # проверка, если читается ключ
        skey = item.decode() # конвертировать bytes=>str
        key = skey[:-1] # убрать '\n'
        fkey = False
    else:
        svalue = item.decode() # конвертировать bytes=>str
        value = int(svalue) # конвертировать str=>int
        D2[key] = value # добавить к словарю
        fkey = True # указать, что на следующей итерации будет ключ

# 3.5. Вывести словарь
print("D2 = ", D2)

# 3.6. Закрыть файл
f.close()

Результат работы программы

D2 = {'One': 1, 'Two': 2, 'Three': 3, 'Four': 4}

Вид файла myfile8.txt

One
1
Two
2
Three
3
Four
4

 

7. Копирование одного бинарного файла в другой

 

# Бинарные файлы. Копирование файлов

# 1. Открыть файлы
f1 = open('myfile8.bin', 'rb') # файл - источник, открывается для чтения
f2 = open('copyfile8.bin', 'wb') # файл - копия

# 2. Считать файл f1 в список строк bstrings
bstrings = f1.readlines()

# 3. Записать список строк bstrings в файл f2
f2.writelines(bstrings)

# 4. Закрыть файлы
f1.close()
f2.close()

 

8. Объединение двух бинарных файлов. Пример

В примере реализована операция объединения двух файлов в результирующий третий файл. Сначала данные с файлов-источников считываются в списки. Затем происходит конкатенация этих списков и запись результирующего списка в файл результата.

# Объединение файлов myfile1.bin+myfile2.bin => myfile3.bin
# 1. Открыть файлы для чтения
f1 = open('myfile1.bin', 'rb')
f2 = open('myfile2.bin', 'rb')

# 2. Считать файлы в списки L1, L2
L1 = f1.readlines()
L2 = f2.readlines()

# 3. Объединить списки
L3 = L1 + L2

# 4. Закрыть файлы myfile1.bin, myfile2.bin
f1.close()
f2.close()

# 5. Открыть файл myfile3.bin для записи
f3 = open('myfile3.bin', 'wb')

# 6. Записать строки в файл
f3.writelines(L3)

# 7. Закрыть результирующий файл
f3.close()

 


Связанные темы