in reply to Opening a File Twice

You're not closing the file from your first step and hence some (or rather, all) lines remain in memory, buffered by Perl or the OS. close the first file or use a lexical filehandle (or both), and you will see the data when you reopen the file.

Replies are listed 'Best First'.
Re^2: Opening a File Twice
by Jamin (Novice) on May 28, 2008 at 14:25 UTC
    I "think" I am closing the filehandle after I create the STEP2 file, but before I access the second time for reading.

    At least I think I am.

    Here is a shortened version of the code:

    ######################## # OPEN THE STEP 1 FILE # ######################## foreach (@files) { chdir($dir1); ## Verify Files exist die "File: $_ does not exist. \n $!" unless -e ; ## Verify Files are read/writable die "File: $_ isn't read or writable \n $!" unless ((-r $_ ) && (-w $_ )); ### Open the file open (FILE, "<", $_ ) or die "Cannot open the file $! \n"; select((select(FILE), $/ = undef)[0]); my @array_contents = <FILE>; close (FILE) or die $!;; ## DO SOME STUFF ########################## # CREATE THE STEP 2 FILE # ########################## chdir($dir2); $outputfile = "STEP2_" . $_; open(OUTFILE, ">" , $outputfile) or die $!; print OUTFILE $contents; close OUTFILE or die $!; }; ########################## # ACCESS THE STEP 2 FILE # ########################## chdir($dir2); open (SFCOMMENTS, "<STEP2_CaseComment.csv") or die "Cannot open Salesf +orce Comments file $! \n"; $count = 0; while (<SFCOMMENTS>) { print "Count is: $count \n"; $count ++; } close SFCOMMENTS or die $!;
      You might want to change
      foreach (@files) {
      to
      foreach my $file (@files) {
      Then you could replace
      $outputfile = "STEP2_" . $_; open(OUTFILE, ">" , $outputfile) or die $!;
      with
      $outputfile = "STEP2_" . $file; open(OUTFILE, ">" , $outputfile) or die "opening $outputfile $!";
      The value of $_ is almost certainly used for more than the name of the file being processed. These changes will guarantee the filename is retained, and associate the actual filename with the error.

      Revise: The foreach was corrected, thanks to moritz kindly pointing out my gaffe.

      With Perl 5.8.5, I can't reproduce your error. I've changed your code around a bit to make it work with strict and removed some of the file tests because they are redundant but still:

      use strict; my @files = qw(CaseComment.csv); my $dir1 = "."; my $dir2 = "."; ######################## # OPEN THE STEP 1 FILE # ######################## foreach (@files) { my $filename = "$dir1/$_"; #chdir($dir1); # replace by "$dir/$_" # Redundant - open() will die with # an informative message anyway ## Verify Files exist #die "File: '$filename' does not exist: $!" # unless -e $filename; ## Verify Files are read/writable #die "File: $filename isn't read or writable \n $!" # unless ((-r $filename ) && (-w $filename )); ### Open the file open (FILE, "<", $filename ) or die "Cannot open the file '$filena +me': $!\n"; #select((select(FILE), $/ = undef)[0]); # what is that for? my @array_contents = <FILE>; close (FILE) or die $!; ## DO SOME STUFF ########################## # CREATE THE STEP 2 FILE # ########################## #chdir($dir2); my $contents = <<TESTCOMMENTS; Line 1 line 2 linE 3 TESTCOMMENTS my $outputfile = "$dir2/STEP2_" . $_; warn "Writing '$contents'"; open(OUTFILE, ">" , $outputfile) or die "Couldn't create '$outputf +ile':$!"; print OUTFILE $contents; close OUTFILE or die $!; }; ########################## # ACCESS THE STEP 2 FILE # ########################## #chdir($dir2); my $commentsfile = "$dir2/STEP2_CaseComment.csv"; open (SFCOMMENTS, "<", $commentsfile) or die "Cannot open Salesforce C +omments file '$commentsfile' : $! \n"; my $count = 0; while (<SFCOMMENTS>) { print "Count is: $count \n"; $count ++; } close SFCOMMENTS or die $!;
      outputs for me:
      C:\Projekte>perl -w tmp.pl Writing 'Line 1 line 2 linE 3 ' at tmp.pl line 44. Count is: 0 Count is: 1 Count is: 2

      Maybe your assignment to $contents is somehow wrong? More debugging information is needed.

      I don't see where your problem has anything to do with the ordering of opens and closes. More likely the records are not getting written correctly. Your code slurps the contents of the input file as one record into the first element of @array_contents then writes $contents out to the second file without any record delimiters. The code provided does nothing when I run it. Have you verified the contents of your written file using a text editor? Can you provide a snippet of code that behaves as you say?

      Two other minor points. You call chdir() inside your foreach(@files) loop. This will only work for absolute path names otherwise the code will try to chdir to a subdirectory from inside a subdirectory. The $count loop displays the first record as a count of 0. While it would be proper to consider this an index of 0, the count should read 1.


      s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}