You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. Données binaires
  2. ================
  3. Introduction : chiffres et nombres
  4. -----------------------------------
  5. Si je vous parle de ce que représente le texte: ``342`` vous pouvez le
  6. voir de deux façons:
  7. 1. C'est une **suite de chiffres**: ``3``, puis ``4``, puis ``2``.
  8. 1. C'est un **nombre** (quelque part entre 300 et 350)
  9. On se sert des *chiffres* de 0 à 9 pour *représenter* des *nombres*
  10. La base 10
  11. ----------
  12. Plus exactement, pour passer de la suite de chiffres ``342`` au nombre,
  13. on part de la fin, puis on ajoute chaque chiffre, multiplié par la puissance
  14. de 10 adéquate::
  15. 2 * 1
  16. + 4 * 10
  17. + 2 * 10 * 10
  18. soit::
  19. 2
  20. + 40
  21. + 300
  22. ce qui fait bien 342.
  23. La base 16
  24. ----------
  25. En informatique, on se sert souvent de la base 16. C'est le même principe: on se
  26. sert des "chiffres" de 0 à F (A vaut 10, B vaut 11, jusqu'à F qui vaut 15)
  27. Ainsi, la suite ``DA2`` peut être interprétée comme suit ::
  28. 2 * 1
  29. + 10 * 16
  30. + 13 * 16 * 16
  31. soit ::
  32. 2
  33. + 160
  34. + 3328
  35. soit 3746
  36. On appelle aussi la base 16 la base *hexadécimale*, ou *hexa* en abrrégé.
  37. La base 2
  38. ----------
  39. La base 2 c'est pareil, mais avec deux "chiffres" - 0 et 1.
  40. Ainsi, la suite `110` peut être interprétée comme suit ::
  41. 0 * 1
  42. + 1 * 2
  43. + 1 * 2 * 2
  44. soit ::
  45. 0
  46. + 2
  47. + 4
  48. soit 6.
  49. Bits et octets
  50. --------------
  51. * Un bit (*bit* en anglais) c'est la valeur 1 ou 0
  52. * Un octet (*byte* en anglais) c'est une suite de 8 bits
  53. À retenir
  54. ---------
  55. **Ces paquets de 8 ne veulent rien dire en eux-mêmes**.
  56. Ils n'ont de sens que dans le cadre d'une *convention*.
  57. Par exemple, l'octet '10100100' peut être un nombre écrit en
  58. binaire (164 en l'occurrence), mais peut avoir une toute
  59. autre signification
  60. Le nombre de valeurs possible augmente *très* rapidement avec le nombre d'octets:
  61. * 1 octet, c'est 255 valeurs possibles (``2 ** 8``)
  62. * 2 octets, c'est 65.536 valeurs possibles (``2 ** 16``)
  63. * 4 octets, c'est 4.294.967.296 valeurs possibles (``2 ** 32``)
  64. Bases en Python
  65. ---------------
  66. On se sert des préfixes `0b` et `0x` pour noter
  67. les nombres en base binaire ou hexadécimale respectivement::
  68. print(0b1110)
  69. # affiche: 6
  70. print(0xDA2)
  71. # affiche: 3490
  72. Poids des bits
  73. --------------
  74. Regardez l'example suivant::
  75. x = 0b0010010 # 18
  76. y = 0b0010011 # 19
  77. z = 0b1010010 # 82
  78. Notez que le premier bit est plus "fort" que le dernier on dit qu'on est en "little endian".
  79. Manipuler des octets en Python
  80. ------------------------------
  81. On peut construrie des listes d'octets en utilsant ``bytearray`` et
  82. une liste de nombres::
  83. data = bytearray(
  84. [0b1100001,
  85. 0b1100010,
  86. 0b1100011
  87. ]
  88. )
  89. # equivalent:
  90. data = bytearray([97,98,99])
  91. # equivalent aussi:
  92. data = bytearray([0x61, 0x62, 0x63]
  93. Texte
  94. -----
  95. On peut aussi interpréter des octets comme du texte - c'est la table ASCII
  96. .. image:: ../img/ascii-table.png
  97. La table se lit ainsi: si on veut connaître la suite de 0 et de 1 qui correspond à `B`: on lit
  98. les 3 premiers bits de haut en bas sur la colonne: `100`, puis les 4 bits sur la ligne: `0010`.
  99. Du coup 'B' en s'écrit en 7 bits: `1000010`, soit 66 en décimal, et 42 en héxadécimal
  100. ASCII - remarques
  101. -----------------
  102. * C'est *vieux* - 1960
  103. * Le A est pour American
  104. * Ça sert à *envoyer* du texte sur des terminaux d'où les "caractères" non-imprimables dans la liste
  105. * Mais c'est une convention *très* utilisée
  106. * Un message de 4 lettres ASCII sera souvent envoyé comme 4 octets (même si seulement 7 bits sont nécessaires)
  107. Utiliser ASCII en Python
  108. ------------------------
  109. Avec ``chr`` et ``ord``::
  110. x = chr(0x42)
  111. print(x)
  112. # affiche: B
  113. x = ord('B')
  114. print(x)
  115. # affiche: 66
  116. Affichage des bytearrays en Python
  117. ----------------------------------
  118. Python utilise ASCII pour afficher les bytearrays si les caractères sont "imprimables"::
  119. data = bytearray([97,98,99])
  120. print(data)
  121. # affiche: bytearray(b"abc")
  122. .. note::
  123. Notez que Python rajoute quelque chose qui ressemble à un
  124. appel de fonction lorsqu'il affiche le bytearray: ce n'est
  125. pas un *vrai* appel de fonction.
  126. Et ``\x`` et le code hexa sinon::
  127. data = bytearray([7, 69, 76, 70])
  128. print(data)
  129. # affiche: bytearray(b"\x07ELF")
  130. Notez bien que ce qu'affiche Python n'est qu'une *interpétation* d'une séquence d'octets.
  131. Types
  132. -----
  133. La variable `b"abc"` est une "chaîne d'octets", de même que `"abc"` est une "chaîne de caractères".
  134. Python apelle ces types `bytes` et `str`::
  135. print(type("abc"))
  136. # affiche: str
  137. print(type(b"abc"))
  138. # affiche: bytes
  139. bytes et bytearray
  140. ------------------
  141. De la même manière qu'on ne peut pas modifier un caractère à l'intérieur une string, on ne peut
  142. pas modifier un bit - ou un octet dans une variable de type `bytes`::
  143. a = "foo"
  144. # a[0] = "f" => TypeError: 'str' object does not support item assignment
  145. b = b"foo"
  146. # b[0] = 1 => TypeError: 'bytes' object does not support item assignment
  147. Par contre on peut modifier un bytearray::
  148. b = bytearray(b"foo")
  149. b[0] = 103
  150. print(b)
  151. # affiche: bytearray(b"goo")
  152. Conversion bytes - texte
  153. ------------------------
  154. Avec ``encode()`` et ``decode()``::
  155. text = "chaise"
  156. encodé = text.encode("ascii")
  157. print(encodé)
  158. # affiche: b"chaise"
  159. bytes = b"table"
  160. décodé = bytes.decode("ascii")
  161. print(décodé)
  162. # affiche: b"table"
  163. Notez que dans le deuxième exemple, on est bien en train de "décoder"
  164. un paquet de 0 et de 1. Il peut s'écrire ainsi:
  165. bytes = b"\x74\x61\x62\x6c\x65"
  166. décodé = bytes.decode("ascii")
  167. print(décodé)
  168. # affiche: table
  169. Plus loin que l'ASCII
  170. ---------------------
  171. Vous avez sûrement remarquer qu'il n'y a pas de caractères accentués dans
  172. ASCII. Du coup, il existe d'autres *conventions* qu'on appelle "encodage".
  173. On peut spécifier l'encodage quand on appelle la méthode ``decode()``::
  174. # latin-1: utilisé sur certains vieux sites
  175. data = bytearray([233])
  176. lettre = data.decode('latin-1')
  177. print(lettre)
  178. # affiche: 'é'
  179. # cp850: dans l'invite de commande Windows
  180. data = bytearray([233])
  181. lettre = data.decode('cp850')
  182. print(lettre)
  183. # affiche: 'Ú'
  184. Notez que la même suite d'octets a donné des résultats différents en fonction
  185. de l'encodage!
  186. Unicode
  187. --------
  188. L'Unicode c'est deux choses:
  189. 1. Une **table** qui associe un un "codepoint" à chaque caractère
  190. 2. Un encodage particulier, l'UTF-8, qui permet de convertir une suite
  191. d'octets en suite de codepoint et donc de caractères
  192. UTF-8 en pratique
  193. ------------------
  194. D'abord, UTF-8 est compatible avec ASCII::
  195. encodé = "abc".encode("utf-8")
  196. print(encodé)
  197. # Affiche: b'abc'
  198. Ensuite, certains caractères (comme ``é``) sont représentés par 2 octets::
  199. encodé = "café".encode("utf-8")
  200. print(encodé)
  201. # Affiche: b'caf\xc3\xa9"
  202. Enfin, certains caractères (comme les emojis) sont représentés par 3 voire plus octets.
  203. .. warning::
  204. Toutes les séquences d'octets ne sont pas forcément valides quand on veut
  205. les décoder en UTF-8
  206. Conséquences
  207. -------------
  208. * On peut représenter *tout* type de texte avec UTF-8 (latin, chinois, coréen, langues disparues, ....)
  209. * On ne peut pas accéder à la n-ème lettre directement dans une chaîne
  210. encodée en UTF-8, il faut parcourir lettre par lettre (ce qui en pratique est rarement
  211. un problème).