Кодировки и работа с файлами

Байтовые структуры

Bytearray нужен не очень часто:

бНОПНЯ

То, что мы в ИТ называем «символами» — соответствие некоторого маркера термину — в действительности суть «знаки». Понятие «символа» слишком многозначно и нередко представляет собой нечто противоположное знаку: символ маркирует целый культурно-ассоциативный корпус, для каждого человека — а тем более в разных культурах — разный.

прекрасная статья про Unicode

Как преобразовать из str в bytes и обратно?

Кодировка
соответствие некоторого числа конкретному символу

Кодировки бывают фиксированного размера и многобайтовые.

⇒ Лучше всегда использовать UTF-8. Остальные ещё хуже.

Представление строк внутри Python:

Не всякие кодировки полны:"Вопрос".encode("koi8-r").decode("latin3")

Устарело ли понятие однобайтовой кодировки? Нет! бНОПНЯ живёт и процветает в Windows, например.

Просто файлы

В tutorial

Отдельная тема: «файлы в операционной системе» — слишком много и не про язык, не будем туда ходить.

Стандартный ввод-вывод

Как обычно: sys.stdin, sys.stdout и sys.stderr — это файлы стандартного ввода, вывода и вывода ошибок соответственно

Двоичные аналоги — sys.stdin.buffer, sys.stdout.buffer и sys.stderr.buffer

Файловые объекты

Более высокий уровень абстракции — io (в действительности более низкий)

Типизированные файлы

В «просто файлы» записываются только строки или байты. А если надо записать float, причём не в виде строки?

Для начала вопрос: а в виде чего?

Сериализация

Чтение и запись объектов Python

Пример:

   1 >>> import pickle
   2 >>> pickle.dumps(0x14131211)
   3 b'\x80\x04\x95\x06\x00\x00\x00\x00\x00\x00\x00J\x11\x12\x13\x14.'
   4 >>> pickle.dumps(0x14131211)[-5:]
   5 b'\x11\x12\x13\x14.'
   6 >>> du = pickle.dumps(123.123e20)
   7 >>> du
   8 b'\x80\x04\x95\n\x00\x00\x00\x00\x00\x00\x00GD\x84\xdb\x9b\xe5\x05\x1cP.'
   9 >>> ud = pickle.loads(du)
  10 >>> ud
  11 1.23123e+22
  12 >>> F = open("serialized", "bw")
  13 >>> pickle.dump(100500, F)
  14 >>> pickle.dump([1, "WER", None], F)
  15 >>> pickle.dump(b"QWWER", F)
  16 >>> F.close()
  17 >>> F = open("serialized", "br")
  18 >>> pickle.load(F)
  19 100500
  20 >>> pickle.load(F)
  21 [1, 'WER', None]
  22 >>> pickle.load(F)
  23 b'QWWER'
  24 

Сериализация экземпляра класса:

Структуры типа Си

Что мешает записать / считать представление объекта в памяти — это и будет в точности его контент?

struct

Простой пример запаковки произвольных данных:

   1 >>> struct.pack("IhBi", 100500, 32100, 200, -6)
   2 b'\x94\x88\x01\x00d}\xc8\x00\xfa\xff\xff\xff'
   3 

Пример: заголовок PNG (возможно, не успеем)

   1 import struct
   2 import zlib
   3 import sys
   4 
   5 HEADER = "8B"
   6 CHUNK = "!I4s"
   7 CRC = "!I"
   8 IHDR = "!IIBBBBB"
   9 
  10 def readpack(fmt, fle):
  11     return struct.unpack(fmt, fle.read(struct.calcsize(fmt)))
  12 
  13 payload = b''
  14 with open(sys.argv[1], "br") as f:
  15     png = readpack(HEADER, f)
  16     print(*map(hex, png))
  17     while (chunk := readpack(CHUNK, f))[1] != b"IEND":
  18         print(*chunk)
  19         data = f.read(chunk[0])
  20         crc = readpack(CRC, f)
  21         if chunk[1] == b"IHDR":
  22             w, h, bpp, col, comp, filt, i = struct.unpack(IHDR, data)
  23             print(f"{w}×{h}, {bpp=}, {col=}, {comp=}, {filt=}, {i=}")
  24         elif chunk[1] == b"IDAT":
  25             payload += data
  26 
  27 print(len(payload), w, h, w*h)
  28 payload = zlib.decompress(payload)
  29 print(len(payload), w, h, w*h)

Базы данных и dict-like итерфейс

dbm

Файлы с известной структурой

Д/З

Ввод для некоторых задач нельзя сделать с клавиатуры — там могут быть произвольные байты. Тем не менее, в программе можно воспользоваться чтением из sys.stdin.buffer, а тестировать так:

Собственно, задание:

  1. Прощёлкать примеры с файлами в Tutorial, а также примеры по pickle и struct

  2. EJudge: TarFile 'Размер архива'

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

    Input:

    1f8b0800000000000003edd64d6ac3301005e059
    f714ba8134d2482abe42c92a2748529365c1690e
    9013147a9ff60cce8de23f085da4c18b51e3f2be
    8d0d3648f0347e664bea5c27c7385ed3cfeb8458
    42483e4a6621c72e4a2013f5b746743cbc6f1a63
    685fbf35fbfaf67bf79e2f14db57f535fa8093c8
    9cfc53ce649cface08f9db9dfa1a77f317bee6df
    9d8521ff84fc4b683fcf27e39d69bfdaeff34777
    e7bd715c8550856456eb97a7bfde20a892c7eaff
    10328ffd2fe8ff12c446f513302fffa1ff33e3ff
    af883effadf21a33fa7fcabffb0078f47f0937fa
    df7325cfe8ffff4fec467d8d79f33ff47f7698ff
    227e99ff88f90700000000000000000058ae0bcd
    cedba200280000
    Output:

    99 4
  3. EJudge: BmpParser 'Анализ BMP'

    Написать программу, разбирающую некоторые заголовки BMP-файла. Ограничения на структуру следующие:

    • Рассматриваются только первые два заголовка: «Bitmap file header» и «DIB header»
    • Необязательные секции отсутствуют или не влияют на разбор
    • Исторический формат «DIB header» — любой (отличаются размерами, всего 8 штук)
    • Если в заголовке указан тип компрессии и размер картинки, этот размер даётся для распакованной картинки (то есть кратен ширине и высоте с учётом глубины цветности)

      • Если ширина картинки в байтах не кратна 4, в конец каждой строки пикселей дописывается недостающее число битов — это влияет на общий размер картинки

    • Также допустимо, чтобы указанный в заголовке размер картинки
      • был равен 0 (тогда он вычисляется из ширины высоты и глубины цвета)
      • был на 2 больше вычисленного размера (я не разобрался, в каких случаях это так)
    • Других заполнителей и выравнивания нет

    Программа должна проверять, соответствуют ли входные данные (weasel2.4c.bmp) структуре BMP-файла, и выводить либо первое найденное несоответствие, либо информацию о файле:

    1. Если в начале файла нет сигнатуры "BM", выводится "Not a Windows BMP"

    2. Если поле «размер BMP-файла» не равно объёмы введённых данных, выводится "Incorrect size"

    3. Если размер DIB header не равен одному из известных, выводится "Incorrect header size"

    4. Если заданный размер картинки не равен вычисленному (с учётом возможного +2 и нулевого значения), выводится "Incorrect image size"

    5. В противном случае выводятся абсолютные значения ширины, высоты и глубины цветности картинки, а также метод упаковки (если не задан, то 0) и размер заполнителя (0 или 2)
    Input:

    …содержимое weasel2.4c.bmp…
    Output:

    82 73 4 0 0
  4. EJudge: EncPairs 'Патриоты Зимбабве'

    Некоторый текст на русском языке в однобайтовой кодировке, содержащий слово «Зимбабве», перекодировали в другую однобайтовую кодировку. Однако исходная и целевая кодировки при этом выбирались случайно — возможно, они не совпадали с кодировкой текста. Ошибок при перекодировке не произошло. Написать программу, которой на вход подаётся результат такой перекодировка, а на выходе должен получиться исходный текст. Доступные кодировки: KOI8-R, CP1251, MACCYRILLIC, CP866, ISO-8859-5, CP855. В примере приведён не сам входной файл, а его дамп.

    Input:

    00000000  bc 9f 96 f6 f0 90 e1 e0  20 80 96 84 20 f3 e0 f0  |........ ... ...|
    00000010  90 e5 2c 20 84 e0 e6 e5  e6 e0 e1 93 e5 96 20 e3  |.., .......... .|
    00000020  e2 93 82 20 e3 e0 90 96  9f e5 e0 94 82 83 e2 f2  |... ............|
    00000030  20 c8 9f c7 92 96 f0 f0  c7 e1 20 e5 20 f2 c7 f6  | ......... . ...|
    00000040  dc e6 e5 96 20 0a f4 20  c7 80 e6 96 83 e0 9f c7  |.... .. ........|
    00000050  f6 83 c7 e3 f1 20 e5 20  e3 c7 f0 f4 c7 e1 f0 f4  |..... . ........|
    00000060  c7 e3 f1 20 f0 e5 90 f1  2c 20 e1 c7 84 9f e0 f0  |... ...., ......|
    00000070  90 e0 9c 90 20 84 e0 20  90 e5 c8 e5 f3 83 e2 f2  |.... .. ........|
    00000080  20 f6 e1 c7 9f 83 e5 f4  c7 e1 2c 20 0a b8 e5 e3  | ........., ....|
    00000090  80 e0 80 e1 96 20 f6 e1  c7 9f 83 e5 f4 e0 20 e5  |..... ........ .|
    000000a0  84 e1 9f e0 e6 e0 dc 20  80 e2 90 e5 96 2e 20 b7  |....... ...... .|
    000000b0  c7 2d f2 e0 e3 f0 f4 e5  20 9c 9f c7 f6 f0 90 e1  |.-...... .......|
    000000c0  f1 9c e6 e0 dc 20 e0 83  e0 9f f2 e5 dc 20 0a f0  |..... ....... ..|
    000000d0  90 9f c7 96 83 e5 dc 20  80 f1 f6 96 90 20 c8 9f  |....... ..... ..|
    000000e0  c7 f6 c7 94 e4 e0 90 82  20 c8 96 90 82 20 c7 20  |........ .... . |
    000000f0  93 e0 c8 f4 96 20 90 9f  e0 83 f0 91 c7 9f e3 e0  |..... ..........|
    00000100  92 e5 e5 2e 20 be 84 83  e0 96 90 20 c7 20 c8 c7  |.... ...... . ..|
    00000110  f0 94 96 f6 83 96 85 20  0a e5 f6 96 e0 94 e5 84  |....... ........|
    00000120  e0 92 e5 e5 20 f0 20 c8  c7 84 83 e0 83 e5 dc e3  |.... . .........|
    00000130  e5 20 f4 e0 c8 e5 90 e0  94 e5 84 e3 20 f0 20 f4  |. .......... . .|
    00000140  c7 94 82 92 c7 e3 2e 20  bf c7 94 f0 90 e0 dc 20  |....... ....... |
    00000150  e5 20 90 c7 83 f4 e0 dc  20 0a 9f e2 80 e0 2c 20  |. ...... ....., |
    00000160  c7 90 9f e0 e4 e0 9c e6  e0 dc 20 80 96 84 c7 80  |.......... .....|
    00000170  9f e0 84 e5 dc 20 c8 9f  e5 84 9f e0 f4 c7 e3 20  |..... ......... |
    00000180  83 e0 92 e5 c7 83 e0 94  82 83 c7 85 20 80 e0 83  |............ ...|
    00000190  e5 2c 20 80 f1 f6 96 90  20 f0 c7 c7 90 e1 96 90  |., ..... .......|
    000001a0  f0 90 e1 c7 e1 e0 90 82  20 0a e0 f4 90 e5 e1 83  |........ .......|
    000001b0  c7 85 20 e5 20 90 9f 96  84 e1 c7 85 20 c7 93 e5  |.. . ....... ...|
    000001c0  80 f4 96 2c 20 e1 e2 c8  e5 e1 93 e5 20 e5 20 9c  |..., ....... . .|
    000001d0  9f c7 f6 f0 90 e1 f1 dc  2e 20 be 90 c7 c8 e5 f3  |......... ......|
    000001e0  96 f0 f4 e5 96 20 f0 f1  e6 83 c7 f0 90 e5 2c 20  |..... ........, |
    000001f0  0a f0 f4 e0 84 e0 83 83  e2 96 20 c7 20 81 e0 94  |.......... . ...|
    00000200  c7 81 96 83 c7 e1 c7 f6  c7 9f c7 f6 e0 f2 20 e5  |.............. .|
    00000210  20 e1 9f 96 e3 96 83 e0  e3 e5 20 f0 20 f0 9f 96  | ......... . ...|
    00000220  f6 f0 90 e1 c7 e3 20 e1  f4 94 9c f3 e0 9c e6 e5  |...... .........|
    00000230  96 0a                                             |..|
    Output:

    Средства без части, защищавшие мышь материальных процессов и ходящие 
    к общенародному и московскому ситу, возрастают за типичных дворников, 
    Зимбабве дворника извращая бытие. По-хамски юродствующая анархия 
    строения будет продолжать петь о шапке трансформации. Узнает о последней 
    идеализации с познаниями капитализм с кольцом. Толстая и тонкая 
    рыба, отражающая безобразия призраком национальной бани, будет соответствовать 
    активной и трезвой ошибке, выпивши и юродствуя. Утопические сущности, 
    сказанные о галогеноводородах и временами с средством включающие

LecturesCMC/PythonIntro2024/11_FilesEncodings (последним исправлял пользователь FrBrGeorge 2024-11-29 18:33:38)