Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

reading file into an array

by vassago (Novice)
on Dec 05, 2008 at 20:39 UTC ( #728372=perlquestion: print w/replies, xml ) Need Help??
vassago has asked for the wisdom of the Perl Monks concerning the following question:

I'm reading a file of 2-3000 lines into an array to process the data in the file. I'm using:
my @fileContents = <$file>
to just dump the whole file into the array. The problem I'm running into is that it appears that perl is breaking it into multiple arrays (two dimensional array) each holding 1000 lines. So when I do something like a for loop:
for(my $x=14; $x<@fileContents; $x++)
to read through each individual line it's only reading the first 999 lines and then stopping (if you are wondering, the data I need to look at starts on line 14). The reason I believe that it is breaking it into two dimensional arrays is because I'm using epic with eclipse and am in debug mode and that's what appears to be happening when I look at the array after the file is read into it.
I was contemplating trying to use:
while(<>) to read everything but I need to start on line 14 or I'm going to get errors.
Any help on this is greatly appreciated. Thank you.

Replies are listed 'Best First'.
Re: reading file into an array
by lostjimmy (Chaplain) on Dec 05, 2008 at 20:53 UTC

    I think we're going to need to see more code. There is no way that you could be getting a multidimensional (read: array of arrays) array from reading a file. I'd like to see what you are doing

    An easy fix to start on line 14 would be something like:

    #!/usr/bin/perl use strict; use warnings; for (1..13) { <DATA>; } while (<DATA>) { print; } __DATA__ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

      When i cut the file into about 500 lines it worked fine, but with my test file of 2800 lines it put out the wrong output. I have it running. I used:
      and just used an arbitrary line counter to have it start processing the code once it hit line 14 and above. I just tested similar code but just had it read the file into the array and then print it out to a text file and checked the text file and it was all there so what I was seeing in eclipse was misleading (I think it breaks it into 1000 line chunks to make it easier to read through manually).
      And I totally just had an 'aha' moment. I was parsing the date out of each line to test it against another file I had to make sure the lines I was comparing are the same date and time. Initially I was only taking the date from line 14 because I at first didn't realize one file would have multiple dates. So when I changed it to parse the date from every line I forgot to change the date reading from
      $fileContents14 to $fileContents$x
      So it wasn't looking like it was going through all the info because the test of making sure the same date is being tested failed for the whole document. And when I tested with only 500 lines the date changed to the correct date within the first 14 lines.
      I don't know if much of that made sense without knowing what the program does and stuff but I now feel stupid for posting this question. I seriously played with this for hours before posting and couldn't figure it out, though.

        It has been my experience that the two best ways to solve a problem are:

        • Ask the question in public where lots of people can see what's confusing you.
        • Tell your boss you can't solve it.

        Either of these activities will cause the solution to manifest itself in very short order.

        G. Wade
Re: reading file into an array
by McDarren (Abbot) on Dec 05, 2008 at 21:03 UTC
    for(my $x=14; $x<@fileContents; $x++)
    Array indexes in Perl begin with zero, so that's actually going to start at line 15.

    Also, a more perlish way of initiating that loop would be:

    for (13 .. $#fileContents) { print "$fileContents[$_]\n"; # Or whatever }
    However, a much better way to process a file line by line is with a while loop. Something like this:
    my $lines_to_skip = 14; while (my $line = <$file>) { # $. will give you the current line number of the file next if ($. <= $lines_to_skip); chomp($line); # Do stuff with $line }

    Hope this helps,
    Darren :)

      Processing line by line in a while loop is a a more scaleable solution but I would prefer to separate the line skipping part from the main line processing logic. I think it keeps things clearer but others may disagree.

      my $linesToSkip = 14; my $discard = <$file> for 1 .. $linesToSkip; while( my $line = <$file> ) { chomp $line; ... }

      Calling the scalar $discard makes it clear that it is something we are not interested in whereas $line might be something we want to work with.

      I hope you find these thoughts of interest.



      I can't help mentioning, because I was so happy when I stumbled across it, the following cute syntax for skipping a constant number of lines using the range operator:
      while ( my $line = <$file> ) { next if 1 .. 14; do_stuff; }
      (Unfortunately, it doesn't work with a variable—for example, next if 1 .. $lines_to_skip—since the range operator just tests whether $lines_to_skip is a true value, not whether it's equal to $..)
      Sorry, it starts on line 15. Thanks for the reply. It is working now. And I like your way of the while loop much better than what I used. However, I'm new to perl and don't fully understand your for loop. I assume the "13 .." just means start at 14 but why is there a '#' in front of the fileContents and why $ instead of @? Java was my first language so perl is very different and its taking a lot of getting used to. Thanks for the replies!
        $# (not #$) refers to the index of the last element of an array.

        The "at-sign" sigil (@) is used when you refer to two or more elements of an array. If you are accessing (or referring to) a single element of an array, then the "dollar-sign" ($) sigil is used.

        For example:

        my @foo = qw/a b c/; print "$foo[1]\n"; # Prints b print "@foo\n"; # Prints a b c print "$foo[$#foo]\n"; # Prints c (but you would probably never do th +is) print "$foo[-1]\n"; # Also prints c (a better way than the previou +s) print "@foo[0,2]\n"; # Prints a c

        Darren :)

        For an array @array, $#array gives the index of the last item in the array. It's a minor piece of cryptic Perl syntax.

        G. Wade
Re: reading file into an array
by SilasTheMonk (Chaplain) on Dec 05, 2008 at 20:54 UTC
    vassago Please do two things:
    1. Give us a link to a wep-page explaining what "epic" is.
    2. Post the code here. Be careful to post the code inside "code" tags as explained in the stuff below the text entry box.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://728372]
Approved by McDarren
[hippo]: Brother dazz is nothing if not persistent.

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (7)
As of 2018-05-24 08:55 GMT
Find Nodes?
    Voting Booth?