Perlでデータを永続化する

投稿日:2019年04月14日 21時28分27秒

Perlを使っていて配列とかハッシュとか保存したいなと思う事があります。私はバッチに近い使い方をしてるので特にそのようなケースが多いのかもしれません。幾つかのブログを参照したところData::Dumperはファイルの内部形式を表現しているという情報がありましたのでこれを使って任意のデータを保存するプログラムを書いてみます。

対象となるデータですが、配列でもハッシュでもその混合でも構いません。ただし代入できるのは1ファイルにつき1つの変数です。Dumperの出力がひとつの変数になるようにアドレスを取って表示します。ハッシュに配列とキーを保存したりする混合形式で保存してもらえると便利に使えるかもしれません。戻す時には$VAR1=という内容のファイルが圧縮して書かれている筈です。またData::Dumperのダンプ形式は格納順番を壊さないようなのでデータ順が問題となる場合にも使えます。さらにある程度大きなデータになることを想定してcompress::Zlibを使って圧縮して保存することにします。
内容を確認したい時はcompress関数を取り除いてください。
呼び出し形式は以下の通りとなります。

書き込み DumpFile(ファイル名,データアドレス);

読み込み ReadFile(ファイル名,データアドレス);

となります。

実行部分は以下の通りです。

#!c:/perl/bin/perl
#***********************************************************************
#
# Data Dumper
#
#***********************************************************************
use strict;
use warnings;
use Data::Dumper;
use Compress::Zlib;

my @a=();
my @b;
my %c;
my %d;
my $filename1=”d:\\dump1.dat”;
my $filename2=”d:\\dump2.dat”;
push(@a,1);
push(@a,2);
push(@a,3);
$c{“aa”}=”bb”;
$c{“bb”}=\@a;
print Dumper(\@a);
DumpFile( $filename1,\@a);
ReadFile( $filename1,\@b);
print Dumper(\@b);
print Dumper(\%c);
DumpFile( $filename2,\%c);
ReadFile( $filename2,\%d);
print Dumper(\%d);
これから呼び出される関数は以下の通りです。

#----------------------------------------------------
# Dump hash to tmporary and rename file
#----------------------------------------------------
sub DumpFile{
my $outPath = shift ;
my $ref_list = shift ;
open (FH,">$outPath") or return 0;
print FH compress(Dumper($ref_list));
close FH;
return 1;
}
#-----------------------------------------------------------------------
# read Dumped hash
#-----------------------------------------------------------------------
sub ReadFile{
    my $targetPath = shift ;
    my $ref_list = shift ;
    my $str,$VAR1;
    # Data::Dumperに依って出力されたファイルを読み込む
    $str = "";
    open (FH,"<$targetPath") or return 0;
    while () {
        $str .= $_;
    }
    close FH;
    # 読み込んだコードを、evalを利用して実行する
    # 保存されたデータは、$VAR1へ格納される
    if( length $str ){
        eval uncompress($str);
        if( ref($ref_list) eq "HASH" ){
            %{$ref_list} = %{$VAR1};
        }elsif( ref($ref_list) eq "ARRAY" ){
            @{$ref_list} = @{$VAR1};
        }
        return 1;
    }else{
        return 0;
    }
}
ReadFile側ではevalされた結果を、引数型に分類して格納しています。現在は配列とarrayまたはその混合を実装してます。
ref関数には他にも以下のような型がありますので組み合わせて別な表現にすることも可能かと思います。関数の保存が出来るかなど確かめて無いことも多いのでやってみた方は教えてください。

ref関数の戻り値
・SCALAR   スカラー
・ARRAY    配列
・HASH    ハッシュ
・REF     リファレンス
・CODE    サブルーチン
・パッケージ名 blessされているもの
・GLOB    型グロブ

[<< Perlコードを最適化する]

[C,C++のインデントをPerlで >>]