FC2ブログ

Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
この記事にトラックバックする(FC2ブログユーザー)
http://katu1109.blog49.fc2.com/tb.php/124-6bc2cc09

トラックバック

コメント

[C279]

お疲れ様です (w

ずいぶん前の話なんですけどね。
VBで通信モジュールを作ったときのことを思い出しましたよ。
VBってVB5だか6だかでいきなり文字コード体系をUnicodeにしたときがありましたでしょ。
あのときに従来のVBで作成された通信モジュールの動作確認をしたことがあったのです。
結果は×。
原因わからなくてハマりましたよ。
で、原因は・・・
通信用のコードACKとかNACKとかまでUnicode化の影響で2バイトにされてたの。
確かにACK、NACK、ENQもキャラ扱いだけどさぁ、
何もそこまで律儀に2バイト化しなくても・・・

な~んで昔話を思い出してしまいました。
  • 2009-07-27 22:09
  • totomn
  • URL
  • 編集

[C281]

へぇ~~~~~。
私はVB5時代は組込みやってたので、
初めて聞きました。

>何もそこまで律儀に2バイト化しなくても・・・
そうですよね。。。
これって通信用ハードが対応できないような???

しかし、これに気づくのは凄いですね。
きっとストリームをバイナリで解析したのですね。
さすがです。
  • 2009-09-07 23:54
  • かつしん
  • URL
  • 編集

コメントの投稿

コメントの投稿
管理者にだけ表示を許可する

文字コード(UTF16-UTF8)と改行コード(CRLF-LF)と正規表現ではまる


合計6時間はまりました。(涙
どなかたの参考になればと思い投稿します。

やりたかったことは、Windows上で作成したxmlファイルをサーバ(Linux)にアップロードして、
xmlファイルの要素lengthの値を抽出すること。(例.<length>600</length>)

アップロード処理は簡単に終わったのですが、値を抽出するところにはまりました。
(5分くらいで終わると思ってたのに・・・。)

結論としては、以下のようにやればOKでした。

STEP1.文字コードを変換(UTF16→UTF8)
STEP2.改行コードを変換(CRLF→LF)
STEP3.正規表現で値を抽出

まず最初に、Rubyに組み込まれているXMLパーサー(REXML)に
バグがあるのかと思ってしまいました。

ファイル形式が違うのでを使っても正しく処理できないのです。
  • ・高速なSAXを使ってみて、ダメ!
  • ・しょうがないからDOMを使ってみても、ダメ!!
  • ・しょうがないからIOライブラリを使って自力で書いても、ダメ!!!

なんでだーーーー!!!

■改行コードの違い


で、ふと、viでファイルを開いている時に、、、
「変換済」という文字が目に入りました。



「あ、改行コードが違うじゃん!!」

そうです。
Windowsの改行はCRLF(”\r\n”)、Linuxの改行はLF("\n")なのです。

この違いは「odコマンド」で確認できます。
コマンド:od -c ファイル名

■Linuxの場合




■Windowsの場合


そこで、CR("\r")を取り除く処理を加えました!!これでバッチリ!!

と思ったら、エディタで読めていたファイルが壊れました(文字化け)・・・。(涙




なんでだーーーー!!!

ファイルをバイナリモードで開いてみたり、色々と試行錯誤しましたが、NG。

■文字コードの違い

次に文字コードの違いに着目しました。
プログラムはUTF-8で処理するように統一しています。
Windowsの日本語の文字コードはSHIFT-JISです。

で、この変換コードを書いてみましたが、、、、、ダメ!!!!!

もう嫌。。。。

そんな時、ふと、odコマンドで、元のファイルを開いてみました。



ん?やたらと「\0」が多いです。それも一個置き。

ここでやっと気づきました。文字コードは「UTF16」です。
よくよく見れば、ファイルの先頭に「UTF16」って出てるジャン!!!
俺のバカバカバカ!!!

これで、文字化けは解消されました。

■正規表現の間違い

さらにおまけで正規表現も間違えました。

NG:/<length>*<\/length>/
OK:/<length>.*<\/length>/

「.」(ドット)があるかないかの違いです。

■完成コード

で、これらを修正して、無事に目的を達することができました。。。。ふぅ。
手順・コードを紹介しておくと。。。

(1)ファイルを開いてデータを読み込む

f = File.open(ファイルモード)
dat = f.read
f.close


(2)文字コード変換(UTF16をUTF8に変換)

dat = Kconv.toutf8(dat)


(3)改行コードを変換(CRLF)からCRを除去

dat = dat.gsub(/\r/,"")


(4)lengthの要素を抽出する

dat.sub(//){ | m |
self.time_limit = m.sub(/<length>/,"").sub(/</length>/).to_i
}
※(4)は「やっつけコード」なので、突っ込みはご勘弁を

■最適化

上記の(2)と(3)はNKFというライブラリを使えば、1個の処理でできることが判明。

dat = NKF.nkf("-w -xm0 -d ",dat)

予想外にはまりましたが、いい勉強になりました。
おそまつ。
スポンサーサイト
この記事にトラックバックする(FC2ブログユーザー)
http://katu1109.blog49.fc2.com/tb.php/124-6bc2cc09

トラックバック

コメント

[C279]

お疲れ様です (w

ずいぶん前の話なんですけどね。
VBで通信モジュールを作ったときのことを思い出しましたよ。
VBってVB5だか6だかでいきなり文字コード体系をUnicodeにしたときがありましたでしょ。
あのときに従来のVBで作成された通信モジュールの動作確認をしたことがあったのです。
結果は×。
原因わからなくてハマりましたよ。
で、原因は・・・
通信用のコードACKとかNACKとかまでUnicode化の影響で2バイトにされてたの。
確かにACK、NACK、ENQもキャラ扱いだけどさぁ、
何もそこまで律儀に2バイト化しなくても・・・

な~んで昔話を思い出してしまいました。
  • 2009-07-27 22:09
  • totomn
  • URL
  • 編集

[C281]

へぇ~~~~~。
私はVB5時代は組込みやってたので、
初めて聞きました。

>何もそこまで律儀に2バイト化しなくても・・・
そうですよね。。。
これって通信用ハードが対応できないような???

しかし、これに気づくのは凄いですね。
きっとストリームをバイナリで解析したのですね。
さすがです。
  • 2009-09-07 23:54
  • かつしん
  • URL
  • 編集

コメントの投稿

コメントの投稿
管理者にだけ表示を許可する

Appendix

便利ツール

中日辞書 北辞郎

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。