Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

`gsub': invalid byte sequence in Windows-31J #21

Open
m-tmatma opened this issue Mar 25, 2019 · 9 comments
Open

`gsub': invalid byte sequence in Windows-31J #21

m-tmatma opened this issue Mar 25, 2019 · 9 comments

Comments

@m-tmatma
Copy link
Member

#13 (comment)
の以下のエラーが出る (ruby 2.4.5 および 2.6.1 で確認) d176c0f を使用。

github_changelog_generator.bat --help のみで発生。
日本語の .github_changelog_generator をうまく扱えない。
.github_changelog_generator から日本語を取り除くとエラーは発生しない。

C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:54:in `gsub': invalid byte sequence in Windows-31J (ArgumentError)
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:54:in `rescue in parse_line!'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:48:in `parse_line!'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:35:in `block in parse!'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:35:in `each'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:35:in `each_with_index'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:35:in `parse!'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser.rb:14:in `parse_options'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator.rb:28:in `initialize'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/bin/github_changelog_generator:5:in `new'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/bin/github_changelog_generator:5:in `<top (required)>'
        from C:/Ruby24-x64/bin/github_changelog_generator:23:in `load'
        from C:/Ruby24-x64/bin/github_changelog_generator:23:in `<main>'
@berryzplus
Copy link

`gsub': invalid byte sequence in Windows-31J (ArgumentError)

このエラーメッセージ、Windows-31Jのマルチバイトシーケンスとして読もうとしたらおかしなバイトシーケンスを見付けました!(キラーン と言ってるように見えます。

Rubyのオプション(=環境変数?)でデフォルトのテキストエンコーディングをShift_JISにしてた、とかいうオチなんではないかと思います。

UTF-8は7bit以上のコードを表現するのに、一定のパターンで各byteの最上位ビットを立てます。
Shift_JISは9bit以上のコードを表現するのに、一定の値を持つLeadByteをくっ付けてBigEndianのマルチバイトシーケンス(2bytes)を作ります。

Shift_JISに存在しないパターンのバイト並びをデコーダに与えたとき、invalid byte sequence というエラーを吐かせるのはよくある実装だと思います。対象ファイルの文字コードはUTF-8っぽいので、文字コード指定なしで読みに行ってI/Oデフォルトの文字コードがWindows-31Jだったらこんな感じのエラーが出て不思議はないと思います。

@ds14050
Copy link

ds14050 commented Apr 20, 2019

どこに Windows-31J として扱われる文字列があるか、というのが肝です。

Rubyが2.0になってから、このマジックコメントを指定しない場合のデフォルトのファイルエンコーディングがUS-ASCIIからUTF-8に変更されました

REM 日本語を扱えるように内部エンコーディングを UTF-8 にする

あとは、ファイルシステムエンコーディングに由来するのかなあ、よくわからんなあ、という感じです。

@berryzplus
Copy link

引用先の記述はコードに関するものです。

言語仕様として、文字列のエンコードを想定しない、になっているにしても、I/OライブラリはC言語で書かれる環境依存のものです。windows向けの移植ではほぼvcrtが使われますがvcrtはバイトシーケンスをロケール依存のマルチバイトシーケンスと解釈します。

I/OのデフォルトはUTF-8にしてそうだったので原因は謎ですが、何らかの理由でシステムデフォルトが使われている可能性はあると思います。

@ds14050
Copy link

ds14050 commented Apr 25, 2019

引用先の記述はコードに関するものです。

1番目はそうです。文字列リテラルや正規表現リテラルがスクリプトエンコーディングの影響を受けるので、外部由来の文字列変数を埋め込んだり連結したりする際にエンコーディングのミスマッチが起きがちです。

2番目の引用が入出力で想定するデフォルトの文字コードについてです。「I/OのデフォルトはUTF-8にしてそうだった」の根拠に当たる部分ですよね。このオプションが実は機能していませんでした(テヘッ なんてのは知ったこっちゃないので、とりあえず別に原因を求めた結果が先のコメントです。

Ruby 2.6.0 リファレンスマニュアル > 多言語化

@berryzplus
Copy link

I/OのデフォルトがUTF-8にしてそうというのは、このコミット db9d666 を見て思ったことです。

ruby.exeの起動オプションになんか指定してる
ので「常に効果をもたらすと思っていたが、実は制約のある指定方法だった」という顛末を想定しています。

特定の関数を使う場合に効果があるとか、特定のパッケージを使う場合には効果がないとか、ありがちだと思います。おそらくバグというよりはオプションの特性に起因する挙動の違いなんじゃないかな、と。

解決策を導き出すために、検証のネタになりそうな仮定を書いてます。

@ds14050
Copy link

ds14050 commented Apr 25, 2019

Ruby 1.9 ですが……

SET RUBYOPT=-EUTF-8:UTF-8 してから irb (対話型プロンプト) で確認した Encoding.default_external と Encoding.default_internal はともに UTF-8 を表すエンコーディングオブジェクトでした。

SET RUBYOPT= してからだと、Encoding.default_external が Windows-31J で、Encoding.default_internal が nil でした。

berryzplus さんの想定はかなりありえることですが、デバッグ環境がなくてはどうにも。実は https://github.com/takke/changelog-sakura/blob/334126dcd8f0df46ea9a2138e6e843841060439d/makeChangeLog.bat を見てもどこで ruby.exe を起動しているのか、実行スクリプトの内容は、などさっぱりわかっていません。

@berryzplus
Copy link

45行目の github_changelog_generator が ruby スクリプトだと思ってました。
中身は見てないのでアレですが、先頭に #!/usr/bin/ruby とか書いてあるのかな?と(ざっくり。

@ds14050
Copy link

ds14050 commented Apr 27, 2019

45行目の github_changelog_generator が ruby スクリプトだと思ってました。

そうだろうとは思います。その中身と思しきものは、別のリポジトリで確認した気がします。しかしあまりにも不確かです。

@berryzplus
Copy link

gem(=rubyのパッケージシステム)だった...orz

じゃ、どうやってRUBYOPTを渡してるんだろう?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants