人生リアルタイムアタック

当面はPython学習帳

Rubyで固定長のCP932(Shift_JIS)ファイルを扱う

哀しいことにCSVなどでなく固定文字列長のCP932ファイルからインポートを行わないといけなくなったのでその対処方法。
ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-darwin15]

データのイメージ

123456abcdef池袋                                          イケブクロ                                           10
123456abcdef目白                                          メジロ                                             10
123456abcdef高田馬場                                      タカダノババ                                        10

全角=2バイト, 半角1バイトという前提でデータファイルが設計されているが、Ruby 2.x で文字列として全角半角問わず1文字は1文字としてカウントされる為、文字数がズレることがある。

対処

byteslice を使い特定バイト位置をスライスする。

irb(main):023:0> File.foreach('test.txt') { |line| p line.byteslice(12...58); p line.byteslice(58...107) }
"\x92r\x91\xDC                                          "
"\xB2\xB9\xCC\u07B8\xDB                                           "
"\x96ڔ\x92                                          "
"Ҽ\xDE\xDB                                             "
"\x8D\x82\x93c\x94n\x8F\xEA                                      "
"\xC0\xB6\xC0\xDE\xC9\xCA\xDE\xCA\xDE                                        "

utf-8に変換する

irb(main):022:0> File.foreach('test.txt') { |line| p line.byteslice(12...58).encode('utf-8', 'cp932'); p line.byteslice(58...107).encode('utf-8', 'cp932') }
"池袋                                          "
"イケブクロ                                            "
"目白                                          "
"メジロ                                              "
"高田馬場                                      "
"タカダノババ                                           "

必要に応じてstripする

irb(main):021:0> File.foreach('test.txt') { |line| p line.byteslice(12...58).encode('utf-8', 'cp932').strip; p line.byteslice(58...107).encode('utf-8', 'cp932').strip }
"池袋"
"イケブクロ"
"目白"
"メジロ"
"高田馬場"
"タカダノババ"

ルビィのぼうけん こんにちは!  プログラミング

ルビィのぼうけん こんにちは! プログラミング