やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

組込ライブラリ(Encoding)

 Rubyの多言語対応(M17N)機能において利用される。

成果物

情報源

Encoding

文字エンコーディング(文字符号化方式)のクラスです。Rubyの多言語対応(M17N)機能において利用されます。

例えば文字列オブジェクトは、文字列のバイト表現の他にそのバイト表現がどのエンコーディングによるものであるかも併せて保持しています。この情報は String#encoding により取得できます。 Encoding オブジェクトを返すメソッドにはこの他に IO#internal_encoding, IO#external_encoding などがあります。

@see 多言語化

M17N プログラミングの基本

プログラマは文字列を扱うときエンコーディングを常に意識しなければいけません。オブジェクトが生成される段階で、適切なエンコーディング情報を持つよう心がけるべきです。文字列が生成されるのは主に「リテラルから」「IOから」「文字列操作から」の 3 通りです。このうち文字列操作に関しては通常 Ruby 実行系が適切に処理しますから、プログラマは 「リテラルから生成」「IO から生成」 の二通りに関して注意する必要があります。 IO から生成される文字列のエンコーディングに関しては IO/多言語化と IO のエンコーディング を参照してください。

 ようするに以下のあたりに気を配れってことか?

N17N 操作
リテラル マジックコメント、__ENCODING__, String.encoding, String.encode, String:decode
IO IO#internal_encoding, IO#external_encoding
文字列操作 Rubyが適切に処理するので対処不要)

メンバ抜粋

特異メソッド

aliases compatible? default_external default_external= 
default_internal default_internal= find list locale_charmap name_list

インスタンスメソッド

ascii_compatible? dummy? inspect name names replicate to_s

定数

ASCII
EUC_JP
ISO_2022_JP
Windows-31J
UTF_8

 文字コード定数はたくさんあるが、日本であれば上記を知っておけば大体OKでは?

文字コード 用途
ASCII 基本。英数字記号
EUC_JP Linuxで使われていることもある?
ISO_2022_JP 日本の電子メールで使われる?
Windows-31J 日本のWindowsで使われる?
UTF_8 世界標準
文字コード 別名
Shift_JIS なし
Windows-31J CP932, csWindows31J, SJIS, PCK

 Windows文字コードは罠。Shift_JISSJISが違うってのがもう罠。もう文字コードと一緒にWindowsも死んでほしい。

aliases, name_list, list

 aliasesは別名のハッシュを返す。

p Encoding.aliases

 name_listは利用可能なエンコーディング名の一覧を返す。

p Encoding.name_list

 listはロード済みエンコーディング一覧を返す。

p Encoding.list

compatible?

 2つのエンコーディングに互換性があればそのエンコーディングを返す。なければnilを返す。

Encoding.compatible?(Encoding::UTF_8, Encoding::CP932)    # => nil
Encoding.compatible?(Encoding::UTF_8, Encoding::US_ASCII) # => #<Encoding:UTF-8>
Encoding.compatible?(Encoding::SHIFT_JIS, Encoding::SJIS) # => nil
Encoding.compatible?("\xa1".force_encoding("iso-8859-1"), "b") #=> #<Encoding:ISO-8859-1>
Encoding.compatible?(
  "\xa1".force_encoding("iso-8859-1"),
  "\xa1\xa1".force_encoding("euc-jp")) #=> nil

default_external

 既定の外部エンコーディングを返す。

p Encoding.default_external #=> #<Encoding:UTF-8>

標準入出力、コマンドライン引数、open で開くファイルなどで、外部エンコーディングが指定されていない場合の既定値として利用されます。

Rubyロケールまたは -E オプションに従って default_external を決定します。ロケールの確認・設定方法については各システムのマニュアルを参照してください。

-E オプションを指定していない場合は、WindowsではUTF-8、その他のOSではロケールに従って default_external を決定します。

default_external は必ず設定されます。Encoding.locale_charmap が nil を返す場合には US-ASCII が、ロケールRubyが扱えないエンコーディングが指定されている場合には ASCII-8BIT が、default_external に設定されます。

[SEE_ALSO] Rubyの起動 locale(1), Encoding.locale_charmap Encoding.default_internal

 既定の外部エンコーディングをセットする。

p Encoding.default_external = Encoding::UTF_8

default_external を変更する前に作成した文字列と、default_external を変更した後に作成した文字列とではエンコーディングが異なる可能性があるため、Ruby スクリプト内で Encoding.default_external を設定してはいけません。代わりに、ruby -E を使用して、正しい default_external で Ruby を起動してください。

 というわけで上記の代入はできるけどやらないほうがいい。

デフォルトの外部エンコーディングがどのように使われるかについては Encoding.default_external を参照してください。

[SEE_ALSO] Rubyの起動 Encoding.default_external

default_internal

 既定の内部エンコーディングを返す。デフォルトはnil

p Encoding.default_internal #=> #<Encoding:UTF-8>
Encoding.default_internal = Encoding::UTF_8

標準入出力、コマンドライン引数、open で開くファイルなどで、内部エンコーディングが指定されていない場合の既定値として利用されます。

String#encode と String#encode! は、引数に Encoding が与えられていない場合、 default_internal を使用します。

文字列リテラルを作成した場合、エンコーディングには default_internal ではなく ENCODING 特殊変数で参照できるスクリプトエンコーディングが使用されます。

default_internal は、ソースファイルの IO.internal_encoding または -E オプションで初期化されます。

[SEE_ALSO] Rubyの起動 Encoding.default_external

 default_externalと同様、コード内でセットできるが、しないほうがいい。

default_internal を変更する前に作成した文字列と、default_internal を変更した後に作成した文字列とではエンコーディングが異なる可能性があるため、Ruby スクリプト内で Encoding.default_internal を設定してはいけません。代わりに、ruby -E を使用して、正しい default_internal で Ruby を起動してください。

デフォルトの内部エンコーディングがどのように使われるかについては Encoding.default_internal を参照してください。

[SEE_ALSO] Rubyの起動 Encoding.default_internal

find

 指定された名前のエンコーディングオブジェクトを返す。

p Encoding.find('utf-8') #<Encoding:UTF-8>

name, names

e = Encoding.find('utf-8')
p e.name #=> "UTF-8"
p e.names #=> ["UTF-8", "CP65001", "locale", "external", "filesystem", "internal"]

所感

 異なる文字コードのOSで同じように動作させるときはエンコーディングを意識せねばならない。

対象環境

$ uname -a
Linux raspberrypi 5.10.52-v7l+ #1441 SMP Tue Aug 3 18:11:56 BST 2021 armv7l GNU/Linux