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

I am opening a file and storing it into a scalar, but to do all the testing I need, it has to be placed into an array where each line is it's own array element. What's wrong with this attempt at it?

Thanks everyone

open (FILE, "$original") or die "Error: $!"; my $lines = <FILE>; my @array = split(/\n/, $lines); close(FILE);

Replies are listed 'Best First'.
Re: reading file into an array
by Zaxo (Archbishop) on May 31, 2004 at 23:45 UTC

    Just make that @lines and forget the split.

    open (FILE, "$original") or die "Error: $!"; my @lines = <FILE>; close(FILE);
    The diamond op does exactly what you wanted in array context.

    After Compline,
    Zaxo

      Thanks, I guess there's something else wrong. The array works fine but when I write it to an output file, it double spaces everything instead of prints an exact replicate. If I s/\n//, everything will be on the same line and that would be messed up too. Any suggestions?
      open (FILE, "> redo-output.txt") or die "Error: $!"; foreach (@lines) { print FILE "$_\n"; } close(FILE);
      Results:
      # Since the submit button was pushed, we have to check to see if t +he username # they typed exists. $passwords is actually the hash we made earl +ier, but since # we are using just ONE value we call our passwords hash as a scal +ar: $passwords. # To lookup a hash key to see if it exists, you use: if (exists $h +ash{"key"}) {}.
      Instead of:
      # Since the submit button was pushed, we have to check to see if the u +sername # they typed exists. $passwords is actually the hash we made earlier, + but since # we are using just ONE value we call our passwords hash as a scalar: +$passwords. # To lookup a hash key to see if it exists, you use: if (exists $hash{ +"key"}) {}.

        The lines in @lines still have their line endings attached, so when you print them with a newline you get doublespacing. Make that,

        for (@lines) { print FILE $_; }
        or just, print FILE @lines; You also could chomp @lines to remove the previous line ends - useful if you need to translate them.

        After Compline,
        Zaxo

        The elements of @lines has newlines. You either need to chomp them:

        chomp(my @lines = <FILE>)

        In which case you print them with:

        print FILE for @lines; # or, to be more verbose foreach my $line (@lines) { print FILE $line }

        Or, you can leave off the chomp, and use the loop:

        print FILE "$_\n" for @lines; # or, to be more verbose foreach my $line (@lines) { print FILE "$line\n"; }

        Either you've removed the newlines or you haven't, your foreach loop has to match.

        Of course, if this is all you're doing with @lines it'd be much simpler, and more kind to memory, to just read and write at the same time:

        print OUTPUT_FILE while <INPUT_FILE>; # or, to be more verbose while ($line = <INPUT_FILE>) { # manipulation of $line goes here. print OUTPUT_FILE $line; }

        perldoc -q 'entire file' covers this topic, 5.6.1's perldoc -q 'line in a file' helps to explain dealing with files, and 5.8.4's perldoc -q 'line in a file' tells you to use Tie::File.

Re: reading file into an array
by davido (Cardinal) on Jun 01, 2004 at 03:47 UTC
    You know, there's another method that I don't see having been mentioned in this thread yet.

    You could use the Tie::File module.

    Some might say it's overkill if all you want is to slurp a file into an array. But the module is great if you want to access the file's lines as though they are in an array, but without the disadvantage of slurping the whole thing into memory at the same time.

    Tie::File also allows for in-place editing; if you alter the contents of one of a a tied array's elements, that change is written to the file.

    use Tie::File; tie my @array, 'Tie::File', Original or die "Error: $!"; # Do your stuff with @array now.

    Enjoy!


    Dave

      While Tie::File is really cool, and all, I never recommend it to newcomers to Perl. I much rather the newcomer get a good understanding of the "primordial" features of the language, than to gloss over them with magic modules that do the same thing at arm's length.

      Once someone has gotten so familiar with the primitives, that such a loop is seen as drudgery, then a module like Tie::File is an interesting diversion or convenience.

      Or suggest it once someone sees the limitations or complications in the classic iteration. For example, to insert two lines before the last forty lines, it would take some marginally creative queueing to accomplish without Tie::File.

      --
      [ e d @ h a l l e y . c c ]

Re: reading file into an array
by TomDLux (Vicar) on Jun 01, 2004 at 01:30 UTC

    The real question is not "how do you read the file into an array". The real question is, "Do you actually need the whole file in memory at the same time? or would your problem be simpler dealing with it one line at a time?"

    while ( my $line = <FILE> ) { process( $line ); }

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re: reading file into an array
by tinita (Parson) on May 31, 2004 at 23:45 UTC
    first, you're reading in the filehandle in scalar context, which only reads one line in.
    to get the whole file into $lines, you have to set $/ to undef (see perlvar), like:

    my $lines = do { local $/; # sets $/ locally to undef; <FILE>; };
    second, then you split the whole file into an array; this could be done easier by reading in in list context: my @array = <FILE>;
Re: reading file into an array
by Happy-the-monk (Canon) on May 31, 2004 at 23:47 UTC

    my @array = <FILE>;

    would be what you were aiming at.

Re: reading file into an array
by meetraz (Hermit) on Jun 01, 2004 at 20:57 UTC
    The easiest and fastest possible way to do this is via File::Slurp.

    use File::Slurp; my @array = read_file('filename.txt');

    That's all there is to it.