質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

3回答

24378閲覧

UTF-8 and Windows-31J (Encoding::CompatibilityError)が直せない

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2017/01/11 10:48

編集2017/01/11 10:54

下記のファイルで蔵書のデータの登録を日本語でして蔵書のデータを表示をすると UTF-8 and Windows-31J (Encoding::CompatibilityError)が出てしまいます。コマンドプロンプトのフォントはMS ゴシックにしてあります。
print "書籍名: "
book_info.title = gets.chomp
print "著者名: "
book_info.author = gets.chomp

print "書籍名: "
book_info.title = gets.chomp.encode("UTF-8")
print "著者名: "
book_info.author = gets.chomp.encode("UTF-8")
にすれば動くのですが教本の通り(下記のファイル)に書けない理由を知りたいと思い質問しました。

# -*- coding: utf-8 -*- require 'date' class BookInfo def initialize( title, author, page, publish_date ) @title = title @author = author @page = page @publish_date = publish_date end attr_accessor :title, :author, :page, :publish_date def to_csv( key ) "#{key},#{@title},#{@author},#{@page},#{@publish_date}\n" end def to_s "#{@title},#{@author}, #{@page}, #{@publish_date}" end def toFormattedString( sep = "\n" ) "書籍名: #{@title}#{sep}著者名: #{author}#{sep}ページ数: #{@page}ページ#{sep}発刊日: #{@publish_date}#{sep}" end end class BookInfoManager def initialize( filename ) @csv_fname = filename @book_infos = {} end def setUp open(@csv_fname, "r:UTF-8") {|file| file.each {|line| key, title, author, page, pdate = line.chomp.split(',') @book_infos[ key ] = BookInfo.new(title, author , page.to_i, Date.strptime(pdate)) } } end def addBookInfo book_info = BookInfo.new( "", "", 0, Date.new ) print "\n" print "キー: " key = gets.chomp print "書籍名: " book_info.title = gets.chomp print "著者名: " book_info.author = gets.chomp print "ページ数: " book_info.page = gets.chomp.to_i print "発刊年: " year = gets.chomp.to_i print "発刊月: " month = gets.chomp.to_i print "発刊日: " day = gets.chomp.to_i book_info.publish_date = Date.new( year, month, day ) @book_infos[key] = book_info puts book_info.publish_date puts @book_infos[key] end require 'pp' def listAllBookInfos puts "\n---------------------------" @book_infos.each { |key, info| print info.toFormattedString puts "\n---------------------------" } end def saveAllBookInfos open(@csv_fname, "w:UTF-8") {|file| @book_infos.each { |key, info| file.print( info.to_csv( key )) } puts "\nファイルへ保存しました" } end def run while true print " 1. 蔵書データの登録 2. 蔵書データの表示 8. 蔵書データをファイルへ保存 9. 終了 番号を選んでください(1,2,8,9) :" num = gets.chomp case when '1' == num addBookInfo when '2' == num listAllBookInfos when '8' == num saveAllBookInfos when '9' == num break; else puts line.encoding end end end end book_info_manager = BookInfoManager.new("book_info.csv") book_info_manager.setUp book_info_manager.run

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

Rubyでは異なった文字コードの文字列を連結することができません。
Atomをデフォルトの状態で使っているということなので
Atomで書いたプログラムの文字コードは「UTF-8」になります。
もし質問者様がWindowsを使われている場合は、コマンドプロンプトの
デフォルトの文字コードは「Shift-JIS」なのでコマンドプロンプトから
入力した文字列の文字コードは「Shift-JIS」になります。
上のプログラムは出力するときに「プログラムに書かれた文字列」を
入力された文字列にくっつけるということを行います。(例「書籍名:ももたろう」)
ここで「UTF-8」と「Windows-31J(=Shift-JIS)」という異なった
文字コードの文字列が連結されてエラーが発生します。
.encode(文字コード)をすることで文字コードを変更することが可能で
コマンドプロンプトから入力される文字列の文字コードを「UTF-8」にして
文字コードをそろえることで普通に動くようになります。
間違っていたら申し訳ないですがLinuxのコマンドプロンプトの
デフォルトの文字コードは「UTF-8」らしいので、その教本の作者様が
Linuxを使用されていてプログラムの文字コードも「UTF-8」の場合は
.encode(文字コード)で文字コードを「UTF-8」にそろえる必要が
ありません。

追記

Ruby

1#encoding : utf-8 2puts "あなたが入力した文字は「#{gets.chomp.encode(__ENCODING__)}」ですね?"

KSwordOfHaste様とたぶん同じ結果になると思います。
__ENCODING__」はこのプログラムの文字コードを表します。
この場合は「#encoding : utf-8」としているので「__ENCODING__」は「UTF-8」
になります。
「#encoding : windows-31J」とすれば「__ENCODING__」は「Window-31J」
になります。
encode("UTF-8")という風に書いていると、プログラムの文字コードを変更したときに
「encodeの括弧の中身を全て変更しないといけない!!」ということになるかもしれません。
KSwordOfHasteがなさっているように、プログラムの文字コードでencodeするように
すれば、自動的にencodeの括弧の中身も変化するようになるので
プログラムの文字コードを変えても括弧の中身を書き換える必要がありません。
文字コードを変更するつもりがない場合はencode("UTF-8")でも大丈夫です。

参考
Encoding

投稿2017/01/11 11:45

編集2017/01/11 13:35
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/01/11 12:09

本ではWindowsですね。 タイトルは作りながら学ぶRuby入門 第2版です。 本に書いてあるコマンドプロンプトの設定にしたのですが残念です。 今回はいい勉強になりました。 ありがとうございます。
KSwordOfHaste

2017/01/11 13:35

自分は「scriptEncoding="このスクリプト".encoding」なんて書きましたがh_aさんの回答から__ENCODING__を使えばよいことが分かりました。自分の方が勉強させてもらいましたw;
退会済みユーザー

退会済みユーザー

2017/01/11 13:37

いえいえ私の文字コードで死にかけた経験が活かせてよかったです。
退会済みユーザー

退会済みユーザー

2017/01/11 13:59

#encoding : utf-8 def addBookInfo book_info = BookInfo.new( "", "", 0, Date.new ) print "\n" print "キー: " key = gets.chomp print "書籍名: " book_info.title = gets.chomp.encode(__ENCODING__) print "著者名: " book_info.author = gets.chomp.encode(__ENCODING__) print "ページ数: " book_info.page = gets.chomp.to_i print "発刊年: " year = gets.chomp.to_i print "発刊月: " month = gets.chomp.to_i print "発刊日: " day = gets.chomp.to_i book_info.publish_date = Date.new( year, month, day ) @book_infos[key] = book_info puts book_info.publish_date puts @book_infos[key] end こういうことですね!確かにエラーがでなくなりました。 こちらだと修正が簡単にできますね。すごいです! ありがとうございます!
退会済みユーザー

退会済みユーザー

2017/01/11 14:14

どうでもよいことですが、個人的にRubyの勉強にはDXrubyというライブラリがおすすめです。 32bit版のRubyじゃないと使えませんが、ゲームが作れます。 何より、画像が表示できるのでコマンドプロンプトの真っ黒な画面より楽し気です。 公式サイト(http://dxruby.osdn.jp/) DXRuby 1.4.5 リファレンスマニュアル(http://mirichi.github.io/dxruby-doc/index.html) DXRubyで 0から作る「ブロック崩し」(http://blog.livedoor.jp/noanoa07/archives/2045851.html)
退会済みユーザー

退会済みユーザー

2017/01/11 14:20

今やってる教本が終わったらやってみようと思います。 おすすめ教材まで教えていただき感謝してます。
退会済みユーザー

退会済みユーザー

2017/01/11 14:29

教本ではなく、ゲームを作るための道具という感じでしょうか。 require"dxruby" Window.loop do end これだけでウィンドウが作れます。 とっても簡単なのでまた機会があれば。
退会済みユーザー

退会済みユーザー

2017/01/11 14:37

空目しました。すみません。
guest

0

もしスクリプトがutf-8で記述されているのだとしたらその中の文字列リテラルのencodingはutf-8になっていると思います。Windows環境でgetsすると文字のencodingはWindows-31j(つまりMicrosoftのShift-JIS)になると思います。

エンコーディングが異なる文字列を連結したりするとこのエラーが起こるみたいですよ?

Encoding::CompatibilityErrorクラス

jrubyの環境しかないのですがやってみるとencodingが異なってもASCII文字onlyの場合は連結できるようですが漢字などが含まれていると連結時にこのエラーになりました。


追記:
ruby初心者なので何がよい方法かはわかりませんが、例えば文字をgetsで外部から入力させる場合は環境によってencodingが変わるため、安全に取り扱うためにスクリプト(あるいは希望する特定のencoding)に合わせてやるのがよいのではないかと思いました。

ruby

1scriptEncoding="このスクリプト".encoding 2... 3s=gets.chomp.encode(scriptEncoding) 4"漢字の文字列"+s

投稿2017/01/11 11:20

編集2017/01/11 11:39
KSwordOfHaste

総合スコア18400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/01/11 12:17

すみません。追記のコードをどのように扱えばいいかわかりません。 回答ありがとうございます。 いい勉強になりました。
guest

0

教本では、文字コードはすべてutf-8になっているんでしょう。

Ruby

1p Encoding.default_external 2p Encoding.default_internal

を実行するとどうなりますか?

投稿2017/01/11 12:04

otn

総合スコア85762

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/01/11 12:19

#<Encoding:Windows-31J> nil という結果が出ました。 エンコードの調べ方を教えていただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問