package HashFile; use strict; use warnings; use bytes; use Fcntl qw(:flock); use IO::File; use Carp; sub new{ my $class = shift; my %cfg = ( file => '', lock => 0, @_); return eval{ my $self = bless { FILE => $cfg{file}, FH => IO::File->new }, $class; croak "Datei nicht festgelegt!" unless $cfg{file}; $self->{FH}->open($cfg{file}, O_CREAT|O_RDWR|O_BINARY) or croak $!; if( $cfg{lock} ){ flock( $self->{FH}, LOCK_EX) || carp "LOCK_EX is not supported!"; } $self; }; } # Datei lesen, gibt das Array bzw. den Hash zurück # Scalarer Kontext: Referenz # Listenkontext: Hash || Array sub read{ my $self = shift; my $fh = $self->{FH}; # Abkürzung $fh->seek(0,0); read( $fh, my $bin, 4 ); my $c = unpack( 'N', $bin) || return wantarray ? () : []; read($fh, my $index, 4*$c); my @index = unpack 'N*', $index; $self->{RAWDATA} = []; foreach my $len(@index){ read($fh, my $buffer, $len); push @{$self->{RAWDATA}}, $buffer; } return wantarray ? @{$self->{RAWDATA}}: $self->{RAWDATA}; } # Datei schreiben sub write{ my $self = shift; @{$self->{RAWDATA}} = @_; my $c = scalar @_ || 0; my $fh = $self->{FH}; # Abkürzung $fh->seek(0,0); $fh->truncate(0); # Anzahl der Array-Elemente packen $fh->print( pack 'N', $c ); # Serialize my $rawdata = ''; foreach my $e( @_ ){ $e = '' unless defined $e; $fh->print( pack 'N', length $e); $rawdata .= $e; } $fh->print($rawdata); } sub DESTROY{ my $self = shift; $self->{FH}->close if $self->{FH}; } 1;######################################################################### __END__ package main; use Data::Dumper; my $hf = HashFile->new( file => '/tmp/hf.bin', # lock => 1 ) or die $@; $hf->write(%ENV); #$hf->write(1,2,3); my %e = $hf->read; #my @a = $hf->read; print Dumper \%e; #print Dumper \@a;