[Python3 入門 14日目]7章 文字列（7.1.1.1〜7.1.1.4）


###7.1.1.2 UTF-8によるエンコード、デコード

外部の世界との間でデータをやり取りするときに良い。以下の二つの手段が必要になる。

- 文字列をバイト列にエンコードする手段
- バイト列を文字列にデコードする手段
- 動的エンコード方式のUTF-8はPython、Linux、HTMLでは標準的なエンコーディングである。
- webページなどから他のソースをコピー&ペーストでPython文字列を作るときは、ソースがUTF-8形式でエンコードされていることを確かめなければならない。(例外が発生する。) 

###7.1.1.3 エンコーディング(記号化)

- 情報の送信側が、伝えたいメッセージ内容を受信側に届く記号の形に変換すること。
- 文字列をエンコードしてバイトにする。
- **UTF-8**は**8ビット可変長エンコーディング**。

```py

#文字列のencode()関数の第一引数はエンコーディング名。
#Unicode文字列"\u2603"を代入
>>> snowman="\u2603"
>>> len(snowman)
1

#このUnicode文字をバイトーシーケンスにエンコードする。
>>> ds=snowman.encode("utf-8")
>>> len(ds)
3
>>> ds
b'\xe2\x98\x83'

```

- **上記のsnowmanはPythonの世界では\u2603と表現されているが、それを外の世界で標準語のになっているutf-8に変換すると
b'\xe2\x98\x83'になる。**

```py

#Unicode文字が有効なASCII文字にもなっている場合でなければエラーになる。
>>> ds=snowman.encode("ascii")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can not encode character '\u2603' in position 0: ordinal not in range(128)

#encode()関数は、エンコード例外を起こしにくくするために第二引数を持っている。デフォルト値は今までのように動作する"strict"で、ASCII以外の文字が使われているとUnicodeEncodeErrorが起きる。

#ignoreを指定することでエンコードできないものを破棄
>>> snowman.encode("ascii","ignore")
b``
#replaceを使えばエンコードできないものは文字を?に置換
>>> snowman.encode("ascii","replace")
b`?`
#unicode-escape形式のPython Unicode文字列を生成する。
>>> snowman.encode("ascii","backslashreplace")
b`\\u2603`
#webページで使えるエンティティの文字列を生成する。
>>> snowman.encode("ascii","xmlcharrefreplace")
b`&#9731;`

```

###7.1.1.4 デコーディング

- 情報の送信側が作成した記号の意味を受信側が読み解く過程をさす
- バイト列をデコードしてUnicode文字列にする。
- **何らかの外部ソース（ファイル、ウェブサイト、ネットワークAPIなど）からテキストを取り出し、Pythonの世界のUnicodeに変換する。**そのテキストはバイト列としてエンコードされている。

```py
#値が`café`のUnicode文字列を作成
>>> place = "caf\u00e9"
>>> place
`café`
>>> type(place)
<class `str`>
#UTF-8形式でエンコードしてplace_bytes変数に代入する。
>>> place_bytes=place.encode("utf-8")
#place_bytesが5バイトであることに注意
#最初の3バイトはASCIIと同じ(UTF-8の長所)1文字ずつ1バイトで、最後éが2バイトでエンコードしている。
>>> place_bytes
b`caf\xc3\xa9`
>>> type(place_bytes)
<class `bytes`>

>>> place2=place_bytes.decode("utf-8")
>>> place2
`café`
#ASCIIデコーダでは0xc3というバイト値がASCIIでは無効でなのでエラーを返す。
>>> place3=place_bytes.decode("ascii")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: `ascii` codec can`t decode byte 0xc3 in position 3: ordinal not in range(128)

#可能な限りUTF-8エンコーディングを使うのが望ましい。
>>> place4=place_bytes.decode("latin-1")
>>> place4
`cafÃ©`
>>> place5=place_bytes.decode("windows-1252")
>>> place5
`cafÃ©`

```

#coffee break　「数と文字について」

- コンピュータは2進数で演算や判断を行なっている。
- **ビット**とは2進数の1桁のこと。
- **16進数**とは人間が理解しやすくするために2進数4桁を「0〜F」の1桁で表現した数え方。
- **バイト**とは16進数2桁(8ビット＝10進数で0〜255)の単位のこと。
- **バイナリー**とは実際にディスプレーに表示される文字は、文字コードをパソコンのOSが文字画像に変換して、表示している。
- イメージファイルは通常「GIF」や「JPG」形式で圧縮して使われる。

例　JPGファイルの中身(バイト文字)

 FFD8FFE0 00104A46 49460001 0101004B 004B0000 FFFE0094 56542D43 6F6D7072 65737320 28746D29 2058696E 67205465
 63686E6F 6C6F6779 20436F72 702E0000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
 00000000 00000000 00000000 00000000 00000000 00000000 0000FFDB 00840010 0B0C0E0C 0A100E0D 0E121110 131828


#感想

7章をやってみて、データの話となり2進数や16進数、バイトとの絡みなどが一気に出てきた。
学生の時に勉強したがもう忘れているのでこの章で少しずつ復習していくこととする。


######参考文献
「Bill Lubanovic著 『入門 Python3』(オライリージャパン発行)」

参考URL
http://zaq.g1.xrea.com/2sinsuu5.htm
https://docs.python.org/ja/3/howto/unicode.html