ASCII-8BITへの変換をどうする的な話

@frsyukiの疑問から始まった流れを追いたくて、関連するツイートをかき集めました。せっかくなので公開します。
2
Sadayuki Furuhashi @frsyuki

Ruby 1.9 で、なぜ UTF-8 から ASCII-8BIT への変換が Encoding::UndefinedConversionError になるのか分からない。バイナリへの変換ができない?

2012-06-23 06:01:44
Sadayuki Furuhashi @frsyuki

str.length の値が変化する変換はエラーになる? UTF-8 → BINARY やBINARY -> UTF-8 への encode は、どちらもエラー。force_encoding しか通らない。

2012-06-23 06:06:10
Sadayuki Furuhashi @frsyuki

UTF-8な文字列が入っているであろうバイナリデータを、UTF-8 な文字列に変換し、変換に失敗したら例外を投げる最も簡単なコードは、

2012-06-23 06:07:49
Sadayuki Furuhashi @frsyuki

data.force_encoding('UTF-8'); raise "invalid encoding" unless data.valid_encoding? か。簡単でないな。

2012-06-23 06:08:50
小崎 資広 (KOSAKI Motohiro) @kosaki55tea

@frsyuki 「変換」がなにを指しているのか分かりませんが、ASCII-8BITはasciiと互換だけどそれいがいは謎なエンコーディングなので文字コード変換的な処理は書きようがないように思います

2012-06-23 06:14:06
Sadayuki Furuhashi @frsyuki

しかし encode('BINARY') が失敗しうるので、UTF-8 な String を external_encoding = 'UTF-8' な IO に書き込む際に、Encoding::UndefinedConversionError が発生しうる。

2012-06-23 06:14:22
Sadayuki Furuhashi @frsyuki

ぃゃ逆だ。external_encoding = 'BINARY' な IO に UTF-8 な文字列を書き込むときに Encoding::UndefinedConversionError が発生しうる

2012-06-23 06:16:02
Sadayuki Furuhashi @frsyuki

@kosaki55tea 文字の変換ではなくて、エンコーディング指定の変換を意図していました。force_encoding('ASCII-8BIT') を使うべきなのでしょうが、IO#write は String#encode(IO#external_encoding) を呼ぶ

2012-06-23 06:17:58
Sadayuki Furuhashi @frsyuki

@kosaki55tea ので、external_encoding = 'ASCII-8BIT' な IO に、String#encoding == "UTF-8" な文字列を書き込んでいるときに、「書き込み先は任意のバイナリフォーマットだから、UTF-8で符号化された文字列を

2012-06-23 06:19:30
Sadayuki Furuhashi @frsyuki

@kosaki55tea 書き込めるだろう」と思っていたら、実際にはASCII非互換の文字列が含まれていた場合に UndefinedConversionError になったので、あれおかしいな?となったわけです。

2012-06-23 06:20:39
Yukihiro Matz @yukihiro_matz

@frsyuki @kosaki55tea @nurse BINARYならどんなエンコーディングからもエラーなく変換できるといいですね。

2012-06-23 13:56:12
成瀬 @nalsh

@kosaki55tea @yukihiro_matz @frsyuki @nurse エラーが出ないというのは気付かないということなので、今の話のユースケースがよくわかってませんが、エラー無視するAPI新設の方がいいんじゃないかなぁ

2012-06-23 14:31:57
小崎 資広 (KOSAKI Motohiro) @kosaki55tea

@nalsh @yukihiro_matz @frsyuki @nurse わたしも分かっているとは言いがたいのですが set_encoding(nil) で動いたと言っていたので set_encoding(BINARY) って直感的じゃない動作するよねって話じゃないかと

2012-06-23 15:48:55
成瀬 @nalsh

@kosaki55tea @yukihiro_matz @frsyuki 古橋さんの発言をさかのぼってみた感じ、IOにexternal encodingを設定すると自動変換が走るようになるっていう罠にはまったようですね。その辺は仕様と実装両方まずくて改善案が出せないのである

2012-06-23 15:55:15
小崎 資広 (KOSAKI Motohiro) @kosaki55tea

@nalsh @frsyuki @yukihiro_matz set_encoding(BINARY) が意味のある動作をするケースが想像つかないので、set_encoding(nil)と等価にするかいきなり例外上がっちゃった方が親切な気がしなくもないとか思いました

2012-06-23 15:58:55
成瀬 @nalsh

@kosaki55tea @frsyuki @yukihiro_matz IO#set_encodingが犯人かというとそれはちょっと違うんじゃないかな。ならstr.encode("ASCII-8BIT")をforce_encoding("ASCII-8BIT")と読み替えるべき

2012-06-23 16:04:14
Yukihiro Matz @yukihiro_matz

@nalsh @frsyuki @kosaki55tea たぶん同じ意味だけど、ASCII- 8BITとBINARYの変換器を、どんなエンコーディングからもそのまま受け入れるものにするのがいいんじゃないかな。

2012-06-23 16:37:27
成瀬 @nalsh

@yukihiro_matz @frsyuki @kosaki55tea Unicodeを8ビット固定長エンコーディングに「文字コード変換」できるわけねーだろJKというモヒカン的感覚だとちょっとひっかかりますね

2012-06-23 16:43:36
成瀬 @nalsh

バイナリアン的には、BINARYは可変長のまじかるエンコーディングだという見解なのだとしたら変換できてしまうのかもしれない

2012-06-23 16:44:44
成瀬 @nalsh

@yukihiro_matz @frsyuki @kosaki55tea そして :xml とか :universal_newline とか指定してた時はどうする問題。なお、str.encode(BINARY)とかする人がとても多いのは知っているので、救うことには反対してません

2012-06-23 16:52:02
Tanaka Akira @tanaka_akr

@yukihiro_matz @nalsh @frsyuki @kosaki55tea 文字を保存する変換器しかなかったところにバイトを保存する変換器を入れると、変換経路を幅優先探索しているところで変な経路が選ばれるはめになる予感がする。対処は可能だろうど変なことだとは思う。

2012-06-23 16:58:10
Yukihiro Matz @yukihiro_matz

@nalsh え?! 違うんですか? Binaryは(ASCII-8BITも)マジカルエンコーディングだと思ってました。

2012-06-23 16:58:14
Yukihiro Matz @yukihiro_matz

@nalsh @frsyuki @kosaki55tea BINARYに改行などないという態度で。ASCII-8BITはASCIIを名乗っているぶん、若干悩ましいですね。

2012-06-23 17:01:38
Tanaka Akira @tanaka_akr

どーしても手を入れるんなら IO 側だろうな。

2012-06-23 17:01:55