none
Encoding.Unicode.GetStringで数値文字列は扱えないのでしょうか? RRS feed

  • 質問

  • 勉強の為、
    VS.NET2003、Framework1.1の環境で
    http://www.microsoft.com/japan/msdn/thisweek/10lines/encrypt_vb.aspx
    にあるソースをほぼそのまま使用して実行していました。
    そのソースをVS.NET2005、Framework2.0の環境に載せて実行したところ、”20070330”のように日付を表す数字文字列を入れた場合に復号化の段階でエラーが起きました。
    .Net FrameWork1.1の時は起きなかったのですが、2.0にしたら起きてしまいました。原因を調べると暗号化した後のバイト配列からEncoding.Unicode.GetStringを使用して文字列化しているところで一部が正常に復元されないようです。
    上記URLのソースのうち変えたのはDesKey、DesIVの設定部分をEncoding.ASCII.GetBytes("EVAL1234")で固定化して使用していました。

    全ての文字列で起こるわけではないようで原因がわかりません。
    この現象についてご存知の方がいらっしゃいましたら代替策などご教授願えないでしょうか。
    よろしくお願いします。

    2007年3月1日 8:34

回答

  •  ナマケモノ さんからの引用

    ただバージョンによってその部分の動作が違うのが不思議ですね。1.1でエラーが出なくても2.0で
    同じ日付文字列を試すとエラーになりました。この部分がちょっともやもやしますが。。

    CLR の1.1と2.0で挙動が違うのは
    ”Unicode 標準に準拠するため”のようです。

    MSDN Home > .NET Framework ホーム > プログラミング情報 > .NET Framework 1.x/2.0 概要 > .NET Framework 2.0 での重大な変更点 > ランタイム変更点 > CLR ランタイム変更点
    http://www.microsoft.com/japan/msdn/netframework/programming/breakingchanges/runtime/clr.aspx
    http://msdn2.microsoft.com/en-us/netframework/aa497241.aspx
    にEncoding.GetBytes()についての記述があるのを見つけました。

    # なぜか、Encoding.GetString()については書いてありませんね…
    # それでも Encoding.GetString()についても同じことだと思います。

    2007年3月2日 17:33

すべての返信

  • たぶん、ストリームに書き出した後Flushをしていないのでbyte列がちゃんと書き出されていないからだと思います。

    … … …
    cs.Write(source, 0, source.Length)
    cs.Flush()
    cs.Close()
    … … …

    2007年3月1日 9:45
  • ごめんなさい先ほどの返信は訂正します、Flushは関係ありませんね。
    これはよく考えたら当たり前だと思います。

    暗号化後のbyte列の中のあるbyteにunicodeの1文字に対応して無い文字コード(サロゲートペアの片方など)がたまたま現れてしまったのだと思います。
    Encoding.Unicode.GetStringでは無視されるので、結果の文字列は正しくありません。Encoding.Unicode.GetBytesでも元には戻りません。

    暗号化データを文字列ではなくもとのbyte[]列が復元できる形で保存してください。

    2007年3月1日 10:42
  • ご回答ありがとうございます。
    なるほど、Encoding.Unicode.GetStringで扱えない文字コードがバイト配列に入っていた可能性が
    あったということですね。
    ただバージョンによってその部分の動作が違うのが不思議ですね。1.1でエラーが出なくても2.0で
    同じ日付文字列を試すとエラーになりました。この部分がちょっともやもやしますが。。
    解りました、バイト配列の内容を保存するよう方向で考えて見ます。
    IIJIMASさん、ありがとうございました。

    2007年3月2日 5:42
  •  ナマケモノ さんからの引用

    ただバージョンによってその部分の動作が違うのが不思議ですね。1.1でエラーが出なくても2.0で
    同じ日付文字列を試すとエラーになりました。この部分がちょっともやもやしますが。。

    CLR の1.1と2.0で挙動が違うのは
    ”Unicode 標準に準拠するため”のようです。

    MSDN Home > .NET Framework ホーム > プログラミング情報 > .NET Framework 1.x/2.0 概要 > .NET Framework 2.0 での重大な変更点 > ランタイム変更点 > CLR ランタイム変更点
    http://www.microsoft.com/japan/msdn/netframework/programming/breakingchanges/runtime/clr.aspx
    http://msdn2.microsoft.com/en-us/netframework/aa497241.aspx
    にEncoding.GetBytes()についての記述があるのを見つけました。

    # なぜか、Encoding.GetString()については書いてありませんね…
    # それでも Encoding.GetString()についても同じことだと思います。

    2007年3月2日 17:33
  • ご返信ありがとうございます。
    参照URLにて確認しました。
    こういう仕様変更がなされていたのですね。知りませんでした。
    私は”サロゲート”なる言葉自体今回のIIJIMASさんの返信ではじめて知った次第でして、
    対になるはずのものの片方を使用していたとは。
    その後、先のレスで仰っていたバイト配列のまま保持する方法で一応出来るようにはなりました。
    情報を提供頂きありがとうございました。

    2007年3月5日 8:11