CIS 33A Perl handout week 10 part 2
Preliminary material should be here.
Sample programs from Clare Nguyen (edited by Ira Oldham)
############## random file access and $. ############
Lecture week 10 hour 2 Example Part 1
#########################
# Copy the contents of a specified file, with changed format # Exactly one argument must be provided # The argument is the name of the file to be read # Each line in the file is a record # Each record contains two fields, separated by : # The first field is a Name # The second field is Age # Example: # John Smith:93 # Each line will be changed in format # The output file will contain: # A minimum of 20 characters, left justified, for the name # A space is written after the name. # A minimum of 3 characters, filled with leading zeros, for # the age # A space is written after the age. # No \n characters are written to "outfile" # For the records in "outfile" to be usable, they must all # be 25 characters long # Thus every name in the input file MUST be # 20 characters or less, and # every age must be 3 characters, or less # The output will be written to a file named "outfile" # verify exactly one argument 1. die "Usage: $0 filename\n" if @ARGV != 1; # Open specified input file, and open "outfile" for output 2. open (IN,"$ARGV[0]") || die "Cannot open $ARGV[0].\n"; 3. open (OUT,">outfile") || die "Cannot open outfile.\n"; # Read a line, reformat it, and write it out 4. while (<IN>) 5. { 6. ($name, $age) = split /:/; 7. $str = sprintf ("%-20s %03d ", $name, $age); 8. print OUT $str; 9. } # Note that "outfile" is written with NO \n characters # print the position at the end of "outfile" # Example: If there are 5 records, each 25 bytes long # The final position will be 125 after reading 5 records, # positioned ready to read a Byte following the last read # The data is in positions 0 through 124 10. $pos = tell(OUT); 11. print "position is $pos\n"; # move back to the beginning 12. seek(OUT,0,0); # should now print 0 Bytes from the beginning 13. $pos = tell(OUT); 14. print "position is $pos\n"; 15. close (IN); 16. close (OUT);
#########################
Lecture week 10 hour 2 Example Part 2
#########################
# read and print the first and last records in "outfile" # "outfile" was created in Part 1 # If the input file met the required specifications, # each record in "outfile" contains exactly 25 characters, # with NO "\n" or other separator between records # Reopen "outfile" for reading 1. open (OUT,"outfile") || die "Cannot open outfile.\n"; 2. $rec_length = 25; # start at the beginning ( default anyway ) 3. seek (OUT, 0, 0); # read and print the first record, which has length 25 Bytes 4. read(OUT, $rec, $rec_length); 5. print "first record is $rec\n"; # seek to 25 Bytes from the end of the file 6. seek (OUT, -$rec_length, 2); # 2 means end # print the position of the beginning of the last record 7. $pos = tell(OUT); 8. print "position is $pos\n"; # read and print the last record 9. read(OUT, $rec, $rec_length); 10. print "last record is $rec\n"; 11. close (OUT);
#########################
Lecture week 10 hour 2 Example Part 3
#########################
# seek, read, and print record 4 # seek and write a new record at the end # seek, read, and print record 3 # NOTE that there is always a seek or tell between # read and write, or write and read # open "outfile" for reading and writing 1. open (OUT,"+<outfile") || die "Cannot open outfile.\n"; 2. $rec_length = 25; # seek to the beginning of the 4th record # print the position # read and print the 4th record 3. seek (OUT, 3*$rec_length, 0); 4. $pos = tell(OUT); # save position of record 4 5. print "position is $pos\n"; 6. read (OUT, $rec, $rec_length); 7. print "fourth record is $rec\n"; # seek to the end # get data for a new record from the user # add the new record at the end # NOT done here: # The new name and age should be checked for length # If you write a record that is not the right length # it will make a mess of the seek activities 8. seek (OUT, 0, 2); 9. print "enter name: "; 10. chomp ($name = <STDIN>); 11. print "enter age: "; 12. chomp ($age = <STDIN>>); 13. $str = sprintf ("%-20s %03d ",$name, $age); 14. print OUT $str; # seek to record 3 (the location saved in $pos is record 4) # read and print record 3 15. seek (OUT, $pos - $rec_length, 0); 16. $pos = tell(OUT); 17. print "position is $pos\n"; 18. read (OUT, $rec, $rec_length); 19. print "third record is $rec\n"; 20. close OUT;
#########################
Lecture week 10 hour 2 Example Part 4
#########################
# Now create a new file, NOT used in parts 1, 2 and 3 # open "fileOut" to write and read 1. open (F,"+>fileOut") || die "Cannot open outFile.\n"; # Request user enter name and age per line # with no spaces in the name # with space between the name and age # User stops with <Ctrl-D> # write the data into "fileOut" in the same format that # we have been using for "outfile", except with \n 2. print "Enter name and age pair per line (^D to end): "; 3. while (chomp ($in = <STDIN>)) 4. { 5. ($name, $age) = split(/\s+/,$in); 6. $str = sprintf("%-20s %03d\n", $name, $age); 7. print F $str; # write to "fileOut" 8. } # seek back to the beginning # print the first record 9. seek (F, 0, 0); 10. $rec = <F>; # this works because there are \n # Without \n, read must be used # to read 25 Bytes 11. print "first record is $rec\n"; # seek and print the last record 12. seek (F, -length($rec), 2); 13. $rec = <F>; 14. print "last record is $rec\n"; 15. close F;
#########################
Lecture week 10 hour 2 Example Part 5
#########################
# open "fileA" for output and write 4 characters # the pointer is now 4, ready to write Byte 5 1. open (F,">fileA") or die "Cannot open fileA\n"; 2. print F "1\n2\n"; # Use the same file handle # "fileA" is automatically closed # open "fileB" for output and write 6 characters # the pointer is now 6, ready to write Byte 7 3. open (F,">fileB") or die "Cannot open fileB\n"; 4. print F "1\n2\n3\n"; 5. close F; # glob will generate names: fileA fileB 6. foreach $file (glob "file[AB]") 7. { 8. open (F,"$file") or die "Cannot open $file\n"; 9. print "$.\n" while <F>; # print all line numbers 10. } 11. close F; # again, the same file handle is used for both files # fileA is automatically closed when the file handle is # reused # but, the line count is NOT reset # prints # 1 # 2 # 3 # 4 # 5 # corresponding to the 2 lines in fileA and 3 lines in fileB