-
Notifications
You must be signed in to change notification settings - Fork 0
/
lab14.py
261 lines (230 loc) · 10.5 KB
/
lab14.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#Куликов Н.В. ИУ7-13Б
#Программа, которая позволяет с помощью меню выполнить
#следующие действия:
#1. Выбрать файл для работы
#2. Инициализировать базу данных (создать либо перезаписать файл и заполнить его записями)
#3. Вывести содержимое базы данных
#4. Добавить запись в произвольное место базы данных
#5. Удалить произвольную запись из базы данных
#6. Поиск по одному полю
#7. Поиск по двум полям
import struct
import os
def menu(file):
#Отрисовка меню
print()
print('Текущий файл: ', file)
print('Ваши возможности:')
print('1. Выбрать файл для работы',
'2. Инициализировать базу данных (создать либо перезаписать файл и заполнить его записями)',
'3. Вывести содержимое базы данных',
'4. Добавить запись в произвольное место базы данных',
'5. Удалить произвольную запись из базы данных',
'6. Поиск по одному полю',
'7. Поиск по двум полям',
'8. Завершение программы', sep = '\n', end = '\n')
#Выбор действия
while True:
n = input('Выберите действие (цифру): ')
print()
if n in '12345678' and n != '':
n = int(n)
break
print('Некорректный ввод! Вы ввели не цифру.')
if n == 1:
file = input('Введите имя файла: ')
menu(file)
elif n == 2:
if file == '':
file = input('Введите имя файла: ')
init(file)
elif n == 3:
if file == '':
file = input('Введите имя файла: ')
output(file)
elif n == 4:
if file == '':
file = input('Введите имя файла: ')
while True:
line_index = input('Введите номер позиции: ')
new_line = input('Введите артикул, название и код страны-производителя через пробел: ')
li = new_line.split()
if len(li) == 3 and all(c.isdigit() for c in li[0]) and li[1].isalpha() and all(c.isdigit() for c in li[2]) and all(c in '1234567890' for c in line_index):
line_index = int(line_index)
break
print('Некорректный ввод! Неправильно указаны атрибуты вставляемой строки и/или номер позиции не является числом')
if line_index * 48 > os.path.getsize(file) or line_index < 1:
print('Некорректный ввод! Номер позиции от 1 до <номер последнего элемента + 1>')
menu(file)
add(file, int(line_index), new_line)
elif n == 5:
if file == '':
file = input('Введите имя файла: ')
while True:
num = input('Введите номер удаляемой записи: ')
if num != '':
break
print('Некорректный ввод! Введите одно целое число.')
num = int(num)
if os.path.getsize(file) < num * 48 or num < 1:
print('Записи с таким номером нет в файле')
menu(file)
else:
remove(file, num)
elif n == 6:
if file == '':
file = input('Введите имя файла: ')
while True:
field = input('Введите поле (Артикул, Название, Страна): ')
element = input('Введите элемент: ')
if any(i == field.lower() for i in ['артикул', 'название', 'страна']):
break
print('Некорректный ввод! Такого поля не существует.')
find_by_one(file, field, element)
elif n == 7:
if file == '':
file = input('Введите имя файла: ')
while True:
field1 = input('Введите 1 поле (Артикул, Название, Страна): ')
field2 = input('Введите 2 поле (Артикул, Название, Страна): ')
element1 = input('Введите 1 элемент: ')
element2 = input('Введите 2 элемент: ')
if any(i == field1.lower() for i in ['артикул', 'название', 'страна']) and any(i == field2.lower() for i in ['артикул', 'название', 'страна']):
break
print('Некорректный ввод! Такого поля не существует.')
find_by_two(file, field1, field2, element1, element2)
else:
print('Программа успешно завершена!')
#Инициализировать базу данных
def init(direction):
try:
file = open(direction, 'wb')
except Exception:
print('Ошибка доступа к файлу')
a = []
while True:
s = input('Введите артикул, название и код страны-производителя через пробел: ')
if s == '':
break
li = s.split()
if len(li) == 3 and all(c.isdigit() for c in li[0]) and li[1].isalpha() and all(c.isdigit() for c in li[2]):
a.append(s)
else:
print('Некорректный ввод данных!')
for i in a:
data = i.split()
file.write(struct.pack(FORMAT, int(data[0]), data[1].encode(), int(data[2])))
file.close()
menu(direction)
#Вывести содержимое базы данных
def output(direction):
try:
file = open(direction, 'rb')
except Exception:
print('Такого файла не существует!')
menu(direction)
print('-' * 68)
print(f'|{"Артикул":^12}|{"Название товара":^40}|{"Код страны":^12}|')
print('-' * 68)
while True:
try:
i = file.read(48)
num, name, date = struct.unpack(FORMAT, i)
name = name.decode().rstrip('\x00')
print(f'|{num:^12}|{name:^40}|{date:^12}|')
except Exception:
break
print('-' * 68)
file.close()
menu(direction)
#Поиск по одному полю
def find_by_one(direction, field, element):
try:
file = open(direction, 'rb')
except Exception:
print('Такого файла не существует!')
menu(direction)
ind = ['артикул', 'название', 'страна'].index(field.lower())
print('-' * 68)
print(f'|{"Артикул":^12}|{"Название товара":^40}|{"Код страны":^12}|')
print('-' * 68)
while True:
try:
i = file.read(48)
num, name, date = struct.unpack(FORMAT, i)
name = name.decode().rstrip('\x00')
if str([num, name, date][ind]) == element:
print(f'|{num:^12}|{name:^40}|{date:^12}|')
except Exception:
break
print('-' * 68)
file.close()
menu(direction)
#Поиск по двум полям
def find_by_two(direction, field1, field2, element1, element2):
print(direction, field1, field2, element1, element2)
try:
file = open(direction, 'rb')
except Exception:
print('Такого файла не существует!')
menu(direction)
ind_field1 = ['артикул', 'название', 'страна'].index(field1.lower())
ind_field2 = ['артикул', 'название', 'страна'].index(field2.lower())
print('-' * 68)
print(f'|{"Артикул":^12}|{"Название товара":^40}|{"Код страны":^12}|')
print('-' * 68)
while True:
try:
i = file.read(48)
num, name, date = struct.unpack(FORMAT, i)
name = name.decode().rstrip('\x00')
if str([num, name, date][ind_field1]) == element1:
if str([num, name, date][ind_field2]) == element2:
print(f'|{num:^12}|{name:^40}|{date:^12}|')
except Exception:
break
print('-' * 68)
file.close()
menu(direction)
#Добавление записи в произвольное место
def add(direction, line_index, new_line):
LINE_SIZE = 48
lines_count = os.path.getsize(direction) // 48
with open(direction, 'r+b') as f:
try:
f.seek(-LINE_SIZE, os.SEEK_END)
while lines_count > line_index - 1:
prev_chunk = f.read(LINE_SIZE)
f.write(prev_chunk)
if line_index == 1:
if lines_count - line_index != 0:
f.seek(-LINE_SIZE * 3, os.SEEK_CUR)
else:
f.seek(0)
else:
f.seek(-LINE_SIZE * 3, os.SEEK_CUR)
lines_count -= 1
except Exception:
pass
if lines_count == 0:
f.seek(0)
elif line_index != 1:
f.seek(LINE_SIZE, os.SEEK_CUR)
data = new_line.split()
f.write(struct.pack(FORMAT, int(data[0]), data[1].encode(), int(data[2])))
menu(direction)
#Удаление произвольной записи
def remove(direction, line_index):
with open(direction, "r+b") as f:
f.seek(48 * line_index)
while True:
line = f.read(48)
if not line:
break
f.seek(-48 * 2, os.SEEK_CUR)
f.write(line)
f.seek(48, os.SEEK_CUR)
f.truncate(os.path.getsize(direction) - 48)
menu(direction)
FORMAT = 'i 40s i'
menu('')