Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Writing to DATA

by sweetblood (Prior)
on Nov 14, 2003 at 16:03 UTC ( [id://307080]=perlquestion: print w/replies, xml ) Need Help??

sweetblood has asked for the wisdom of the Perl Monks concerning the following question:

Dear Brethren/Sistren:

Is there a way to programatically write(modify) the contents of DATA? By DATA I mean the data after the __END__ label in my script. Specifically, I what to keep a crc value embeded in my script to verify a data file prior to opening it. But after opening it I will be modifying this data file and will want to re-calculate and rewrite my embeded crc. I've tried to print DATA "whatever", but I get the following error:
Filehandle DATA opened only for input at write_data line 4.

Many Thanks!

Replies are listed 'Best First'.
Re: Writing to DATA
by BrowserUk (Patriarch) on Nov 14, 2003 at 16:11 UTC
      This is great, but probably more complicated than I need as I only need. I will however squirrel this tip away for another day!

      Thanks!

        Inline::Files is pretty easy, I use it for exactly what you describe:

        use Inline::Files; #... # Get the cached MD5 sum open MD5_SUM or die $!; my $prev_md5_sum = <MD5_SUM>; $prev_md5_sum =~ s!\s*!!sg; close MD5_SUM or die $!; # Get the current MD5 sum open(FH, $file) or die "Can't open '$file': $!"; binmode(FH); my $curr_md5_sum = Digest::MD5->new->addfile(*FH)->hexdigest; close FH; # Quit if this file has changed since the last run die "MD5 sums do not match" unless $curr_md5_sum eq $prev_md5_sum; # Write the new checksum use vars qw($MD5_SUM); open MD5_SUM, ">$MD5_SUM" or die $!; print MD5_SUM $curr_md5_sum; close MD5_SUM or die $!; __END__ maybe have some other stuff here... __MD5_SUM__ f8889c135c8342fc394616c3d34f37c2
Re: Writing to DATA
by Anonymous Monk on Nov 14, 2003 at 16:25 UTC

    The DATA filehandle is just a an open handle on the current file. The current file is just the $0 variable (so long as you haven't changed it). So:

    # main part of script ... # then redo the crc: rewrite_crc('datafile'); sub rewrite_crc { my $file = shift; open(SELF,"+<$0")||die $!; while(<SELF>){last if /^__END__/} print SELF new_crc($file),$/; truncate(SELF,tell SELF); close SELF; } sub new_crc { my $file = shift; my $crc = 0; # calculate new crc here $crc = 43256; return $crc; } __END__ 1234567
      In my experience, at least on some platforms, truncate right after print may fail. You need an intermediate seek to be safe.
      print SELF new_crc($file),$/; seek SELF, 0, 1; truncate(SELF, tell SELF);
      See also perldoc -f seek:
      Due to the rules and rigors of ANSI C, on some systems you have to do a seek whenever you switch between reading and writing.

      Perhaps you don't need the truncate — or the seek. CRCs tend to all be the same string length.

      That's pretty darn clever, except that I think you meant to do the trucate prior to the print in rewrite_crc(), otherwise it prints the new crc then truncates it. But this is the basic idea I was looing for.

      What a great place our monestary is! Not to mention the fine people!

      Thanks and be well!

        No. The truncate call works fine where it is, the file will be truncated at its current position (after the write). Of course, you can truncate first and then write too.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://307080]
Approved by BazB
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-04-24 00:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found