エンコーディング

Ruby 1.9.1 のエンコーディングをいろいろ試してみる。

#!/usr/local/bin/ruby19
# -*- coding: shift_jis; -*-

RUBY_VERSION                    # => "1.9.1"
ENV['LANG']                     # => "ja_JP.SJIS"

__ENCODING__                    # => #<Encoding:Shift_JIS>

Encoding.default_external       # => #<Encoding:Windows-31J>
Encoding.default_internal       # => nil
Encoding.locale_charmap         # => "Windows-31J"

`rm -rf encoding.txt`

str = "こんにちは"
str.encoding                    # => #<Encoding:Shift_JIS>

open('encoding.txt', 'w'){|f| f.puts str}

buf = open('encoding.txt'){|f| f.read}
buf.encoding                    # => #<Encoding:Windows-31J>

Encoding.compatible?(str.encoding, buf.encoding) # => nil

Regexp.new(str) =~ buf
# => incompatible encoding regexp match (Shift_JIS regexp with Windows-31J string) (Encoding::CompatibilityError)

Shift_JISWindows-31Juncompatible incompatible なのね。*1

スクリプトWindows-31J で書くことは ... できないんだろうなぁ。

なんとかファイルから読んだ内容を Shift_JIS にできないものか。

もしかして LANG がまずいのか?
LANG を消して、やってみる。

#!/usr/local/bin/ruby19
# -*- coding: shift_jis; -*-

RUBY_VERSION                    # => "1.9.1"
ENV['LANG']                     # => ""

__ENCODING__                    # => #<Encoding:Shift_JIS>

Encoding.default_external       # => #<Encoding:Windows-31J>
Encoding.default_internal       # => nil
Encoding.locale_charmap         # => "CP932"

`rm -rf encoding.txt`

str = "こんにちは"
str.encoding                    # => #<Encoding:Shift_JIS>

open('encoding.txt', 'w'){|f| f.puts str}

buf = open('encoding.txt'){|f| f.read}
buf.encoding                    # => #<Encoding:Windows-31J>

Encoding.compatible?(str.encoding, buf.encoding) # => nil

Regexp.new(str) =~ buf
# => incompatible encoding regexp match (Shift_JIS regexp with Windows-31J string) (Encoding::CompatibilityError)

Encoding.locale_charmap が違うだけか。

Encoding.default_internal を変更してみる。

#!/usr/local/bin/ruby19 -E:Shift_JIS
# -*- coding: shift_jis; -*-

RUBY_VERSION                    # => "1.9.1"
ENV['LANG']                     # => "ja_JP.SJIS"

__ENCODING__                    # => #<Encoding:Shift_JIS>

Encoding.default_external       # => #<Encoding:Windows-31J>
Encoding.default_internal       # => #<Encoding:Shift_JIS>
Encoding.locale_charmap         # => "Windows-31J"

`rm -rf encoding.txt`

str = "こんにちは"
str.encoding                    # => #<Encoding:Shift_JIS>

open('encoding.txt', 'w'){|f| f.puts str}

buf = open('encoding.txt'){|f| f.read}
buf.encoding                    # => #<Encoding:Shift_JIS>

Encoding.compatible?(str.encoding, buf.encoding) # => #<Encoding:Shift_JIS>

Regexp.new(str) =~ buf          # => 0

これが正解なのかな?

でもこれって、読み込みのタイミングで Windows-31J から Shift_JIS への変換が起ってるんだよねぇ。

サポートレベルが "perhaps" な Cygwin 版だから?
mswin32 版だと違うのかなぁ。

*1:Encoding.compatible?("Windows-31J", "Shift_JIS") すると # が返ってくるのはバグ?
Encoding.find(name) でエンコーディング名を文字列で渡せるので、Encoding.compatible?(str1, str2) もエンコーディング名を文字列で渡すのかと勘違いした。