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

Hello All!

I've poked around a good bit, and futzed a lot with this, to no avail, so..... here's the question.

Looking at this node, i'm told that it's pretty easy to add a line to the beginning of a file:

Here's another common problem which is trivially solved by Tie::File. How do I add a new record at the beginning of a file instead of at the end? unshift @lines, $new; # Or add more than one record
Pretty much the same thing is said in the Tie::File pod

My problem is that my code (below the readmore) appears to:

  1. Overwrite the first line of the target file, rather than insert a new first line.
  2. Overwrite part of the next (second) line if the text being inserted is longer than the previous first line (the one being overwritten)

What do i want? I want to have the line in question inserted at the beginning of the file, as described in the quote/outtake above. It seems obvious that i'm doing something wrong, but i can't figure out what. I've pasted the offending sub below (yes, the script is running with -w), as well as some the STDERR output.

Thanks greatly for your attention!

#################### sub update_threads() { my $parent = $_[0]; my $msg_id = $_[1]; #check if this is a top-level, and set $parent accordingly if ($parent eq 'top') { $parent = $msg_id } my $main_threads_file = $htdocs . $path_info . "/threads.html"; my $archive_threads_file = $htdocs . $path_info . "/posts/" . $date . +"threads.html"; my $post_location = $path_info . "/posts/" . $date . "/" . $parent . " +_" . $msg_id . ".html"; my $post_name = $parent . "_" . $msg_id; my @threads; my @archive; my $link = "<li> <!-- mid=\"$post_name\" --> <a href=\"$post_location\ +">" . $params{"subject"} . "</a> by " . $params{"name"} . " <font si +ze=\"-1\">on " . $time . "</font>"; tie @threads, 'Tie::File', $main_threads_file or syslog('err', "update +_threads couldn't open file: $main_threads_file"); if ($parent == $msg_id) { unshift @threads, $link; } untie @threads; return; } ## end sub update_threads() #***************************
the STDERR Below (can i nest readmore tags? hmmm) is the full output to the STDERR during one run... i know much of it is irrelevant, and i strongly suspect that the Tie::File errors are irrelevant too, but i'm not sure...

anyhow,

main::get_date() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 50. main::read_config() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 53. main::print_postform() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 63. main::read_mcount() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 90. main::get_date() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 92. main::generate_post() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 95. main::update_threads() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 98. main::get_date() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 50. main::read_config() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 53. main::print_postform() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 63. main::read_mcount() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 90. main::get_date() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 92. main::generate_post() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 95. main::update_threads() called too early to check prototype at /usr/local/apache/cgi-bin/bthreads-perl line 98. Use of uninitialized value in read at /usr/lib/perl5/5.6.1/Tie/File.pm line 699. Use of uninitialized value in read at /usr/lib/perl5/5.6.1/Tie/File.pm line 699. Use of uninitialized value in read at /usr/lib/perl5/5.6.1/Tie/File.pm line 699. Use of uninitialized value in read at /usr/lib/perl5/5.6.1/Tie/File.pm line 699. Use of uninitialized value in read at /usr/lib/perl5/5.6.1/Tie/File.pm line 699. Use of uninitialized value in read at /usr/lib/perl5/5.6.1/Tie/File.pm line 699. Use of uninitialized value in read at /usr/lib/perl5/5.6.1/Tie/File.pm line 699. Use of uninitialized value in read at /usr/lib/perl5/5.6.1/Tie/File.pm line 699. Use of uninitialized value in read at ## and so on

update (broquaint): changed <pre> tags to <code> and dropped a chunk of repeated error messages

Replies are listed 'Best First'.
Re: Tie::File strangeness with unshift
by CombatSquirrel (Hermit) on May 26, 2003 at 00:03 UTC
    Without knowing much about Tie::File, it seems that you either don't know or have forgot about the concept of prototyping.
    Whe you define a sub in Perl, you do it by writing
    sub NAME { CODE }
    There is another option though, which is prototyping. This means that you can provide the compiler with additional information to facilitate the calls to your subroutine. this prototyping is done with the following syntax
    sub NAME (PROTOTYPES) { CODE }
    Note the additional parens. When PROTOTYPES is the empty string, i.e. when you just provide parens, the compiler will always call your function in a void context and the @_ array will be empty.
    You get the first few error messages, because the compiler "knows" that the sub is prototyped but it doesn't know the prototype yet, I don't know about the last few error messages.
    In any case, changing your function declaration to
    sub update_threads() {
    should at least eliminate the first few error messages.

    P.S.: Which part of your code has what line number?
      Hah.. good point... i'd been ignoring those warnings, intending to fix them later.

      The "line 699" referred to (over and over, i shoulda cut that out!) is actually in the Tie:File code, i think.

      My guess is that the -w flag triggers those warnings when i read stuff using Tie::File in other parts of the script. They were there, and apparently not hurting anything, before.

      The new error is the last bit about FH, but i don't know what it means.

Re: Tie::File strangeness with unshift
by Limbic~Region (Chancellor) on May 26, 2003 at 00:04 UTC
    914,
    As I mentioned in the Chatter Box, can you provide a small snippet of code that reproduces your problem. I can't seem to reproduce it. Typically when trying to create such a reproducible snippet you will find and correct your own problem. Additionally, even with readmore tags - it would have probably been better just to get a unique list of the error messages and perhaps a total count if you felt so inclined.

    Cheers - L~R

      Thanks...

      As you suggest, i've created a new, short and dumb script that does something similar. Of course it works, i doubt the problem is anywhere but in my own code...

      #!/usr/bin/perl -Tw use Tie::File; use strict; my @array; my $file = "./file.txt"; my $line = "this is a really long line of text (sortof)"; tie @array, 'Tie::File', $file; unshift @array, $line; untie @array
        914,
        I noticed you are using the -T option for tainting. Is this running as a CGI? In a nutshell, taint is designed to ensure that Perl doesn't do anything externally by using information obtained externally. I don't think this is your problem, but I figured it was worth pointing out.

        Ok - so you have done the first step - eliminate the possibility that you have a bad copy of Tie::File by proving that it can work. Now you need to find out what it is about your code that breaks it.

      • Trim out the fat. This includes, but is not limited to removing all print statements and things not related to the problem.
      • Run the script again - if the problem is still there, go back to the first step
      • If the problem goes away - then you have discovered that something you thought was innocuous actually wasn't - you have found your own problem.
      • If you have removed all the fat that you can possibly remove and the problem is still there - post that code - that way we can see exactly what you are seeing

        Cheers - L~R

Re: Tie::File strangeness with unshift
by BrowserUk (Patriarch) on May 26, 2003 at 00:55 UTC

    Is it possible that when you installed Tie::File v0.93, you did it somewhere other than your .../perl/lib directory? .../perl/site/lib maybe?

    I ask, because looking at line 699 of v0.93 show it to be a comment line. The error makes sense in the context of line 699 of v0.95 though.

    I also get an error on line 699 when I tried v0.95 in conjunction with perl 5.6.1. Although it was a different error. I got:

    Parentheses missing around "my" list at e:/Perl/lib/Tie/File.pm line 6 +73. Parentheses missing around "my" list at e:/Perl/lib/Tie/File.pm line 6 +99.

    You can check which version is being found like this:

    C:\test>perl -mTie::File -e "print $Tie::File::VERSION" 0.95

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
      line 699 in v0.95 (which i'm using, see above) is:
      read $fh, $old, $readsizei;
      And... it turns out that when i was "uninstalling" 0.95 as mentioned above, it wasn't being uninstalled... i found the offending file (to look at it above) and renamed it.

      The test script now magically works ( locate File.pm reports another copy of File.pm, that one is v0.93)

        914,
        I couldn't let this drop - glad that you found the problem. I am intrigued though. Are you sure line 699 is exactly as you have written it above? I just downloaded it and mine reads:

        read $fh, my $old, $readsize;

        Notice the my infront of old and no i at the end of $readsize. I wonder if someone was hacking what they shouldn't have been. In anycase, if you are confident the problem is with v.095 let Dominus know, but be sure to include a test case he can reproduce.

        Cheers - L~R

Re: Tie::File strangeness with unshift (resolution)
by u914 (Pilgrim) on May 26, 2003 at 01:20 UTC

    Update!

    The issue *really* was that my copy of Tie::File v0.95 was corrupted...

    many thanks to everyone who peeked in!

    I think i've got this licked, but there's some lingering questions. Here's the facts as i've found them:

    1. Tie::File v0.95 appears to have an issue at line 699
      • This is what STDERR complains about
      • The same error appears for my complex script as the simple test script
    2. v0.93 appears not to have this problem
      • line 699 is a comment, so obviously there was a change ;-)
    3. Accusing such a storied mod as Tie::File of having a bug is more than i'm ready for.
        Still, shouldn't someone tell the author?

    For what it's worth, the 0.95 version was installed at: /usr/lib/perl5/5.6.1/Tie/File.pm and the 0.93 at: /usr/lib/perl5/site_perl/5.6.1/Tie/File.pm

    When i renamed the 0.95 version, Perl 'found' the 0.93 and started using is (i expected an error).

Re: Tie::File strangeness with unshift
by BrowserUk (Patriarch) on May 26, 2003 at 02:00 UTC

    It's possible, but not certain, that this is related to a known bug in Tie::File v0.95 as discussed here.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller