📄 db_file.pm
字号:
interface methods (DB_HASH, DB_BTREE or DB_RECNO) is to be used.Depending on which of these is actually chosen, the final parameter,I<openinfo> points to a data structure which allows tailoring of thespecific interface method.This interface is handled slightly differently in B<DB_File>. Here isan equivalent call using B<DB_File>: tie %array, 'DB_File', $filename, $flags, $mode, $DB_HASH ;The C<filename>, C<flags> and C<mode> parameters are the directequivalent of their dbopen() counterparts. The final parameter $DB_HASHperforms the function of both the C<type> and C<openinfo> parameters indbopen().In the example above $DB_HASH is actually a pre-defined reference to ahash object. B<DB_File> has three of these pre-defined references.Apart from $DB_HASH, there is also $DB_BTREE and $DB_RECNO.The keys allowed in each of these pre-defined references is limited tothe names used in the equivalent C structure. So, for example, the$DB_HASH reference will only allow keys called C<bsize>, C<cachesize>,C<ffactor>, C<hash>, C<lorder> and C<nelem>. To change one of these elements, just assign to it like this: $DB_HASH->{'cachesize'} = 10000 ;The three predefined variables $DB_HASH, $DB_BTREE and $DB_RECNO areusually adequate for most applications. If you do need to create extrainstances of these objects, constructors are available for each filetype.Here are examples of the constructors and the valid options availablefor DB_HASH, DB_BTREE and DB_RECNO respectively. $a = new DB_File::HASHINFO ; $a->{'bsize'} ; $a->{'cachesize'} ; $a->{'ffactor'}; $a->{'hash'} ; $a->{'lorder'} ; $a->{'nelem'} ; $b = new DB_File::BTREEINFO ; $b->{'flags'} ; $b->{'cachesize'} ; $b->{'maxkeypage'} ; $b->{'minkeypage'} ; $b->{'psize'} ; $b->{'compare'} ; $b->{'prefix'} ; $b->{'lorder'} ; $c = new DB_File::RECNOINFO ; $c->{'bval'} ; $c->{'cachesize'} ; $c->{'psize'} ; $c->{'flags'} ; $c->{'lorder'} ; $c->{'reclen'} ; $c->{'bfname'} ;The values stored in the hashes above are mostly the direct equivalentof their C counterpart. Like their C counterparts, all are set to adefault values - that means you don't have to set I<all> of thevalues when you only want to change one. Here is an example: $a = new DB_File::HASHINFO ; $a->{'cachesize'} = 12345 ; tie %y, 'DB_File', "filename", $flags, 0777, $a ;A few of the options need extra discussion here. When used, the Cequivalent of the keys C<hash>, C<compare> and C<prefix> store pointersto C functions. In B<DB_File> these keys are used to store referencesto Perl subs. Below are templates for each of the subs: sub hash { my ($data) = @_ ; ... # return the hash value for $data return $hash ; } sub compare { my ($key, $key2) = @_ ; ... # return 0 if $key1 eq $key2 # -1 if $key1 lt $key2 # 1 if $key1 gt $key2 return (-1 , 0 or 1) ; } sub prefix { my ($key, $key2) = @_ ; ... # return number of bytes of $key2 which are # necessary to determine that it is greater than $key1 return $bytes ; }See L<Changing the BTREE sort order> for an example of using theC<compare> template.If you are using the DB_RECNO interface and you intend making use ofC<bval>, you should check out L<The 'bval' Option>.=head2 Default ParametersIt is possible to omit some or all of the final 4 parameters in thecall to C<tie> and let them take default values. As DB_HASH is the mostcommon file format used, the call: tie %A, "DB_File", "filename" ;is equivalent to: tie %A, "DB_File", "filename", O_CREAT|O_RDWR, 0666, $DB_HASH ;It is also possible to omit the filename parameter as well, so thecall: tie %A, "DB_File" ;is equivalent to: tie %A, "DB_File", undef, O_CREAT|O_RDWR, 0666, $DB_HASH ;See L<In Memory Databases> for a discussion on the use of C<undef>in place of a filename.=head2 In Memory DatabasesBerkeley DB allows the creation of in-memory databases by using NULL(that is, a C<(char *)0> in C) in place of the filename. B<DB_File>uses C<undef> instead of NULL to provide this functionality.=head1 DB_HASHThe DB_HASH file format is probably the most commonly used of the threefile formats that B<DB_File> supports. It is also very straightforwardto use.=head2 A Simple ExampleThis example shows how to create a database, add key/value pairs to thedatabase, delete keys/value pairs and finally how to enumerate thecontents of the database. use warnings ; use strict ; use DB_File ; use vars qw( %h $k $v ) ; unlink "fruit" ; tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0640, $DB_HASH or die "Cannot open file 'fruit': $!\n"; # Add a few key/value pairs to the file $h{"apple"} = "red" ; $h{"orange"} = "orange" ; $h{"banana"} = "yellow" ; $h{"tomato"} = "red" ; # Check for existence of a key print "Banana Exists\n\n" if $h{"banana"} ; # Delete a key/value pair. delete $h{"apple"} ; # print the contents of the file while (($k, $v) = each %h) { print "$k -> $v\n" } untie %h ;here is the output: Banana Exists orange -> orange tomato -> red banana -> yellowNote that the like ordinary associative arrays, the order of the keysretrieved is in an apparently random order.=head1 DB_BTREEThe DB_BTREE format is useful when you want to store data in a givenorder. By default the keys will be stored in lexical order, but as youwill see from the example shown in the next section, it is very easy todefine your own sorting function.=head2 Changing the BTREE sort orderThis script shows how to override the default sorting algorithm thatBTREE uses. Instead of using the normal lexical ordering, a caseinsensitive compare function will be used. use warnings ; use strict ; use DB_File ; my %h ; sub Compare { my ($key1, $key2) = @_ ; "\L$key1" cmp "\L$key2" ; } # specify the Perl sub that will do the comparison $DB_BTREE->{'compare'} = \&Compare ; unlink "tree" ; tie %h, "DB_File", "tree", O_RDWR|O_CREAT, 0640, $DB_BTREE or die "Cannot open file 'tree': $!\n" ; # Add a key/value pair to the file $h{'Wall'} = 'Larry' ; $h{'Smith'} = 'John' ; $h{'mouse'} = 'mickey' ; $h{'duck'} = 'donald' ; # Delete delete $h{"duck"} ; # Cycle through the keys printing them in order. # Note it is not necessary to sort the keys as # the btree will have kept them in order automatically. foreach (keys %h) { print "$_\n" } untie %h ;Here is the output from the code above. mouse Smith WallThere are a few point to bear in mind if you want to change theordering in a BTREE database:=over 5=item 1.The new compare function must be specified when you create the database.=item 2.You cannot change the ordering once the database has been created. Thusyou must use the same compare function every time you access thedatabase.=back =head2 Handling Duplicate Keys The BTREE file type optionally allows a single key to be associatedwith an arbitrary number of values. This option is enabled by settingthe flags element of C<$DB_BTREE> to R_DUP when creating the database.There are some difficulties in using the tied hash interface if youwant to manipulate a BTREE database with duplicate keys. Consider thiscode: use warnings ; use strict ; use DB_File ; use vars qw($filename %h ) ; $filename = "tree" ; unlink $filename ; # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE or die "Cannot open $filename: $!\n"; # Add some key/value pairs to the file $h{'Wall'} = 'Larry' ; $h{'Wall'} = 'Brick' ; # Note the duplicate key $h{'Wall'} = 'Brick' ; # Note the duplicate key and value $h{'Smith'} = 'John' ; $h{'mouse'} = 'mickey' ; # iterate through the associative array # and print each key/value pair. foreach (sort keys %h) { print "$_ -> $h{$_}\n" } untie %h ;Here is the output: Smith -> John Wall -> Larry Wall -> Larry Wall -> Larry mouse -> mickeyAs you can see 3 records have been successfully created with key C<Wall>- the only thing is, when they are retrieved from the database theyI<seem> to have the same value, namely C<Larry>. The problem is causedby the way that the associative array interface works. Basically, whenthe associative array interface is used to fetch the value associatedwith a given key, it will only ever retrieve the first value.Although it may not be immediately obvious from the code above, theassociative array interface can be used to write values with duplicatekeys, but it cannot be used to read them back from the database.The way to get around this problem is to use the Berkeley DB API methodcalled C<seq>. This method allows sequential access to key/valuepairs. See L<THE API INTERFACE> for details of both the C<seq> methodand the API in general.Here is the script above rewritten using the C<seq> API method. use warnings ; use strict ; use DB_File ; use vars qw($filename $x %h $status $key $value) ; $filename = "tree" ; unlink $filename ; # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE or die "Cannot open $filename: $!\n"; # Add some key/value pairs to the file $h{'Wall'} = 'Larry' ; $h{'Wall'} = 'Brick' ; # Note the duplicate key $h{'Wall'} = 'Brick' ; # Note the duplicate key and value $h{'Smith'} = 'John' ; $h{'mouse'} = 'mickey' ; # iterate through the btree using seq # and print each key/value pair. $key = $value = 0 ; for ($status = $x->seq($key, $value, R_FIRST) ; $status == 0 ; $status = $x->seq($key, $value, R_NEXT) ) { print "$key -> $value\n" } undef $x ; untie %h ;that prints: Smith -> John Wall -> Brick Wall -> Brick Wall -> Larry mouse -> mickeyThis time we have got all the key/value pairs, including the multiplevalues associated with the key C<Wall>.To make life easier when dealing with duplicate keys, B<DB_File> comes with a few utility methods.=head2 The get_dup() MethodThe C<get_dup> method assists inreading duplicate values from BTREE databases. The method can take thefollowing forms: $count = $x->get_dup($key) ; @list = $x->get_dup($key) ; %list = $x->get_dup($key, 1) ;In a scalar context the method returns the number of values associatedwith the key, C<$key>.In list context, it returns all the values which match C<$key>. Notethat the values will be returned in an apparently random order.In list context, if the second parameter is present and evaluatesTRUE, the method returns an associative array. The keys of theassociative array correspond to the values that matched in the BTREEand the values of the array are a count of the number of times thatparticular value occurred in the BTREE.So assuming the database created above, we can use C<get_dup> likethis: use warnings ; use strict ; use DB_File ; use vars qw($filename $x %h ) ; $filename = "tree" ; # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE or die "Cannot open $filename: $!\n"; my $cnt = $x->get_dup("Wall") ; print "Wall occurred $cnt times\n" ; my %hash = $x->get_dup("Wall", 1) ; print "Larry is there\n" if $hash{'Larry'} ; print "There are $hash{'Brick'} Brick Walls\n" ; my @list = sort $x->get_dup("Wall") ; print "Wall => [@list]\n" ; @list = $x->get_dup("Smith") ; print "Smith => [@list]\n" ; @list = $x->get_dup("Dog") ; print "Dog => [@list]\n" ;and it will print: Wall occurred 3 times Larry is there There are 2 Brick Walls Wall => [Brick Brick Larry] Smith => [John] Dog => []=head2 The find_dup() Method $status = $X->find_dup($key, $value) ;This method checks for the existence of a specific key/value pair. If thepair exists, the cursor is left pointing to the pair and the method returns 0. Otherwise the method returns a non-zero value.Assuming the database from the previous example: use warnings ; use strict ; use DB_File ; use vars qw($filename $x %h $found) ; my $filename = "tree" ; # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE or die "Cannot open $filename: $!\n"; $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ; print "Larry Wall is $found there\n" ; $found = ( $x->find_dup("Wall", "Harry") == 0 ? "" : "not") ; print "Harry Wall is $found there\n" ; undef $x ; untie %h ;prints this Larry Wall is there Harry Wall is not there=head2 The del_dup() Method $status = $X->del_dup($key, $value) ;This method deletes a specific key/value pair. It returns0 if they exist and have been deleted successfully.Otherwise the method returns a non-zero value.Again assuming the existence of the C<tree> database use warnings ; use strict ; use DB_File ; use vars qw($filename $x %h $found) ; my $filename = "tree" ; # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE or die "Cannot open $filename: $!\n"; $x->del_dup("Wall", "Larry") ; $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ; print "Larry Wall is $found there\n" ; undef $x ; untie %h ;prints this Larry Wall is not there=head2 Matching Partial Keys The BTREE interface has a feature which allows partial keys to bematched. This functionality is I<only> available when the C<seq> methodis used along with the R_CURSOR flag.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -