UTF-8 and Windows-31J (Encoding::CompatibilityError)が直せない
- 評価
- クリップ 0
- VIEW 12K+

退会済みユーザー
下記のファイルで蔵書のデータの登録を日本語でして蔵書のデータを表示をすると 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
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
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」にそろえる必要が
ありません。
追記
#encoding : utf-8
puts "あなたが入力した文字は「#{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
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
もしスクリプトがutf-8で記述されているのだとしたらその中の文字列リテラルのencodingはutf-8になっていると思います。Windows環境でgetsすると文字のencodingはWindows-31j(つまりMicrosoftのShift-JIS)になると思います。
エンコーディングが異なる文字列を連結したりするとこのエラーが起こるみたいですよ?
Encoding::CompatibilityErrorクラス
jrubyの環境しかないのですがやってみるとencodingが異なってもASCII文字onlyの場合は連結できるようですが漢字などが含まれていると連結時にこのエラーになりました。
追記:
ruby初心者なので何がよい方法かはわかりませんが、例えば文字をgetsで外部から入力させる場合は環境によってencodingが変わるため、安全に取り扱うためにスクリプト(あるいは希望する特定のencoding)に合わせてやるのがよいのではないかと思いました。
scriptEncoding="このスクリプト".encoding
...
s=gets.chomp.encode(scriptEncoding)
"漢字の文字列"+s
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
教本では、文字コードはすべてutf-8になっているんでしょう。
p Encoding.default_external
p Encoding.default_internal
を実行するとどうなりますか?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.33%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/01/11 21:09
タイトルは作りながら学ぶRuby入門 第2版です。
本に書いてあるコマンドプロンプトの設定にしたのですが残念です。
今回はいい勉強になりました。
ありがとうございます。
2017/01/11 22:35
2017/01/11 22:37
2017/01/11 22:59
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 23:14
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 23:20
おすすめ教材まで教えていただき感謝してます。
2017/01/11 23:29
require"dxruby"
Window.loop do
end
これだけでウィンドウが作れます。
とっても簡単なのでまた機会があれば。
2017/01/11 23:37