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

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

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

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

1回答

12220閲覧

railsにてyamlファイルを出力する際に、yamlファイルの中身に日本語が含まれている場合

domingojapan

総合スコア26

Ruby

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

0クリップ

投稿2016/06/25 00:11

###前提・実現したいこと
ruby単体で動作確認した処理をrailsでも動作するようにlibフォルダに移植しています。
最終的に所定のフォルダに所定のファイル名のyamlファイルを保存する処理になります。

###該当のソースコード
//今後出力ファイルに出力するyaml_fileに値をセットする
def setting_dates(inputdates)
yaml_file = {
'timestamp' => inputdates[0],
'value' => inputdates[1],
'color' => inputdates[2],
}
end

//yamlファイルを出力
def output_yaml_file
open('sample_output.yml', 'w') do |e|
YAML.dump(yaml_file , e)
end
end

//method_hogehogeにて、setting_datesメソッドの引数inputdatesにセットするデータを作成し、返す。
//method_hogehogeの処理の中身は割愛する
//配列inputdatesの各要素にはいずれも文字列が入ります。
inputdates = method_hogehoge
setting_dates(inputdates)
output_yaml_file

###発生している問題・エラーメッセージ
配列inputdatesに格納されているデータ(inputdates[0]/[1]/[2]各々)に日本語の文字列が一切含まれていなければ
エラーが発生する事なくsample_output.ymlが生成されます。生成されたymlの中身も狙い通りです。
ですが、データ(inputdates[0]/[1]/[2])のいずれかに日本語の文字列が含まれていれば
コマンドプロンプト上に
Encoding::UndefinedConversionError ("\xE3" from ASCII-8BIT to UTF-8):
が表示され、エラーとなります。YAML.dumpの箇所です。

###試したこと
上記output_yaml_fileメソッド内の
open('sample_output.yml', 'w') do |e|

open('sample_output.yml', 'wb')
にすると、日本語の文字列が含まれていても。
エラーが発生する事なくsample_output.ymlが生成されます。
sample_output.ymlをテキストエディタで開いても、中身は狙い通りの文字列が入っていました。
日本語の文字も文字化けはしていませんでした。

###確認したい事
Railsだと日本語文字列がバイナリ扱いされるなどの理由で今回の問題が発生していると考えているのですが、あっていますでしょうか?

あっている場合、対策を教えていただければ幸いです。
(試したことに記述したように"wb"でバイナリにすればyamlファイルは生成されるのですが、中身は本当に文字列だけのテキストなのでバイナリというのもなぁという感覚があります)

###補足情報(言語/FW/ツール等のバージョンなど)
OSはWindows7 64bit
Rubyは2.2.5
Railsは4.2.1
エディタはatomで文字コードはrubyではスタンダードのUTF-8にしています。

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

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

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

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

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

guest

回答1

0

バイナリと言うよりも、inputdates[0]/[1]/[2]それぞれのエンコードがASCII-8BITとして設定されていることが問題と思われます。inputdates[0].encodingなどで、文字コード確認してみてください。たぶん、ASCII-8BITとなっています。

###どうしてエラーになるのか

Rubyでは全てのString(文字列)について、文字コードが設定されています。たとえ、内部が同じバイト列であっても、どのような文字コードとして設定しているかによって、その意味が異なります。

Ruby

1# String.new時にエンコード指定はRuby2.3から使えます。Ruby2.3.0以上で試してください。 2p String.new([0xE3, 0x81, 0x82, 0xE4, 0xBA, 0x9C].pack("C*"), encoding: Encoding::UTF_8) 3p String.new([0xE3, 0x81, 0x82, 0xE4, 0xBA, 0x9C].pack("C*"), encoding: Encoding::ASCII_8BIT)

前者は"あ亜"とUTF-8の文字として認識してくれますが、後者は"\xE3\x81\x82\xE4\xBA\x9C"というただのバイトの並びとして認識しており、この二つは異なる文字列として扱っています。同じバイト列だからといって、ASCII-8BITからUTF-8に変換しようとしても、RubyはASCII部分(0x00-0x7f)まではASCII-8BITとUTF-8が同じであることは知っていますが、それ以外(0x80-0xff)の部分はどう解釈して良いかわかりません。そのため、そのまま変換しようとした場合はエラーになります。

この文字コードを意識する動きはファイルの読み書きの時も同じです。UTF-8として開いたファイルはUTF-8として読み書きされます※1。もし、UTF-8のファイルへ、UTF-8ではないEUC-JPの文字コードのStringを書き込もうとした場合、RubyはUTF-8に変換してから書き込みます。YAML.dumpでも同様な動きするため、ASCII-8BITの文字列をUTF-8に変換しようとしますが、上で書いた理由により変換に失敗します※2。

※1 ファイルを比較時のデフォルト文字コードはEncodinge.default_externalの値になります。通常Encodinge.default_externalは実行されたOSの環境に従い、Windowsでは通常Windows-31Jです。しかし、Railsなどのアプリではあらゆる環境で動作するようにしたい場合は、文字コードを指定しておく場合があります。今回は、どこかで既に指定しているはずです。

※2 YAML.dumpでASCII-8BITはバイナリ値に変換される場合もあるようです。

###どうすればいいのか

いくつか方法があります。

  1. inputdates[0]/[1]/[2]を初めからUTF-8として認識させる。(推奨)

どこから取り出したデータかわかりませんが、そのデータをRubyの文字列として認識させる段階でUTF-8に設定しておきます。データベースから取っている場合などは文字コードを指定しないとASCII-8BITになるので注意してください。
日本語を使用する場合は、全ての文字列をUTF-8として認識させることを推奨します。ASCII-8BITのままですと、正規表現の処理やリテラルな文字列(別途UTF-8になっているはず)の結合のときに同じようなエラーが発生したり、意図せぬ動作をします。inputdatesの読み込み部分を見直してください。
2. YAML用データを作るときに、強制的に変換させる。
YAML用データを作るときに、inputdates[0].encode(Encoding::UTF_8, Encoding::UTF_8)等として、UTF-8で認識させたものをUTF-8の文字列として生成します。かなり強引な方法です。また、不正なUTF-8の場合はデフォルトだとエラーになりますので、不正な場合はどうするかなどオプションを追加してください。(詳しくはリファレンスを読んでください)
3. ASCII-8BITとしてファイルを開く。(未検証)
うまくいくかどうかわかりませんが、open('sample_output.yml', 'w:ASCII-8BIT')としてファイルの方を合わせてしまいます。'wb'と似たような動作になるはずです。

投稿2016/06/25 01:30

raccy

総合スコア21735

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問