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