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()

 


Зв’язані теми