October 30, 2010
Read Binary File in Perl
Problem
Given the path to a directory. Write a Perl script to print the average time to open and read all files in that directory. The files should be read in blocks of 64 KB
Solution
This is straightforward problem but we need to pay attention to the fact that files can grow in size so we should not dump the entire file into memory however we will read the file in chunks. For more details please refer to the code below.
Code
Here is the code in Perl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
#!/perl/bin/perl # Command line argumens my $Args = "@ARGV"; # Path to the directory containing files if ($Args =~ /--dir (S+)/) { $dir = $1; } # Hardcoded for testing purpose only $dir = "/perl/test"; # Check tool usage if (!(defined($dir))) { print "\\n"; print "Usage: question_one.pl [--dir <dir>]\\n"; print "\\n"; exit; } print "Please wait...\\n\\n"; # Open directory containing files then read files opendir(DIR, $dir) || die "can not opendir $dir: $!"; @files = readdir(DIR); closedir DIR; # Start time my $StartTime = time(); # Read files one by one foreach $file (@files) { # Exclude the following directory entries . and .. if ($file !~ m/^.|..$/) { #Open file in binary mode open (F, $dir . "/" . $file) or die "can not open file: $!"; binmode(F); #Read file in 64K blocks my ($buf, $data, $n); while (($n = read F, $data, 65536) != 0) { print "Reading $n bytes from file: $file\\n"; $buf .= $data; } close(F); print "\\n"; } } # End time my $EndTime = time(); # Elapsed time my $ElapsedTime = $EndTime - $StartTime; # Number of files read my $NumberFiles = $#files - 1; # Calculate average if ($NumberFiles > 0 and $ElapsedTime > 0) { my $AverageTime = $ElapsedTime/$NumberFiles; print "Number of files read: $NumberFiles\\n"; print "Average time: $AverageTime\\n"; } else { print "No files were found or the files are too small\\n"; } |