はちゅにっき

こっちのブログはまったり更新

FreezeThaw で変数を保存

これぞチェックポイントリカバリ手法。
詳しい使い方はこちらに載ってました。

http://d.hatena.ne.jp/minesouta/20070924

へー。便利。

ただし、データに改行が含まれているとエラーが発生するみたい。
これのせいでどれだけ悩まされたことか。

ところで、変数の情報をそのまま保存するってことは
utf8 フラグのついた文字列とかも
decode せずにファイルに出力しても大丈夫なのかな?
とゆーことで確認。

use utf8;
use strict;
use warnings;

use FreezeThaw qw( freeze thaw );
use Data::Dumper;
use Devel::Peek;

binmode(STDERR, ':encoding(euc-jp)');

{
    my $str = '日本語';
    Dump $str;

    print "-----\n";

    my $freeze = freeze $str;
    print STDERR Data::Dumper::Dumper($freeze);

    {
        open(my $fh, '>', 'freeze');
        print $fh $freeze;
        close $fh
    }

    print "-----\n";

    my @thaw;

    {
        open(my $fh, '<', 'freeze');
        @thaw = thaw <$fh>;
        close $fh;
    }

    print STDERR Data::Dumper::Dumper(@thaw);

    print "-----\n";

    print STDERR $thaw[0], "\n";
}


出力は

SV = PV(0x999b39c) at 0x9901348
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,POK,pPOK,UTF8)
  PV = 0x9a191e8 "\346\227\245\346\234\254\350\252\236"\0 [UTF8 "\x{65e5}\x{672c
  CUR = 9
  LEN = 10
-----
$VAR1 = "FrT;\@1|\$3|\x{65e5}\x{672c}\x{8a9e}";
Wide character in print at test.pl line 22.
-----
Extra elements in frozen structure: `本語' at test.pl line 32

どう考えてもアウトです。本当にありがとうございました。
ちなみに freeze の中身は

FrT;@1|$3|日本語

vimで見ると utf8 としてきちんと認識されていました。
あ、そいえばエラーも32行目(ファイルからの読込)で
出力に関してはエラーを出してないなー。
とゆーことは?ファイルから読み込む際に encode してあげればOK?

use utf8;
use strict;
use warnings;

use FreezeThaw qw( freeze thaw );
use Data::Dumper;
use Devel::Peek;

binmode(STDERR, ':encoding(euc-jp)');

{
    my $str = '日本語';
    Dump $str;

    print "-----\n";

    my $freeze = freeze $str;
    print STDERR Data::Dumper::Dumper($freeze);

    {
        open(my $fh, '>', 'freeze');
        print $fh $freeze;
        close $fh
    }

    print "-----\n";

    my @thaw;

    {
        open(my $fh, '<', 'freeze');
        binmode($fh, ':encoding(utf8)');  # ここでエンコードする
        @thaw = thaw <$fh>;
        close $fh;
    }

    print STDERR Data::Dumper::Dumper(@thaw);

    print "-----\n";

    print STDERR $thaw[0], "\n";
}

出力は

SV = PV(0x81eb388) at 0x8151348
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,POK,pPOK,UTF8)
  PV = 0x8267c70 "\346\227\245\346\234\254\350\252\236"\0 [UTF8 "\x{65e5}\x{672c}\x{8a9e}"]
  CUR = 9
  LEN = 10
-----
$VAR1 = "FrT;\@1|\$3|\x{65e5}\x{672c}\x{8a9e}";
Wide character in print at test.pl line 22.
-----
$VAR1 = "\x{65e5}\x{672c}\x{8a9e}";
-----
日本語

わ。できた。
とゆーことは、結局当たり前だけど、例えば euc-jp で保存したければ、保存する際に

binmode($fh, ':encoding(euc-jp)')

euc-jp に decode して、読み込む際には

binmode($fh, ':encoding(utf8)')

をする必要があるってことですね。

結論。
utf8 フラグの文字列は encode すれば保存できるみたい。