8. Input - Output

We discern in this chapter three input situations:

  • Input via source code (8.1)
  • Input via terminal (8.2)
  • Input via files (8.3)

8.1 Input via source code

while (<DATA>) {  # a way to read all lines under __DATA__ sequentially
print(uc($_)); # output: LINE1, LINE2 etc. on separate lines
}

__DATA__
line1
line2
line3
line4
Another option assigning the DATA to an array (output is the same):

@lines = <DATA>;
foreach $line (@lines) {
 print(uc($line));
}

__DATA__
line1
line2
line3
line4
Notice that the lines under __DATA__ end with a newline character. Use chomp to remove them:

@lines = <DATA>;
chomp(@lines);
etc.

8.2 Input via terminal

print "Your name?"
$name = <STDIN>; # a way to read user input via terminal
chomp($name); # remove newline character
print("Your name: $name");
Somewhat shorter:
print "Your name?"
chomp($name = <STDIN>);
print("Your name: $name");

8.3 Default built-in open and close file functions

The built-in functions open and close are convenient for reading and writing files. However, the module Path::Tiny makes your IO-life easier, providing handy utilities, which we discuss later (see Part 3, Challenges 8 and 9).

To create a new file (FH = FileHandle):
open(FH, '>', $file) or die "Could not open file '$file' $!";close(FH);
To write some data to a file:
open(FH, '>', $file) or die "Could not open file '$file' $!";print(FH "testdata\n");close(FH);
Be aware, the previous command erases all data of the file.

To delete a file, use:
unlink($file); || die ("can not unlink '$file'");
To open and print a file for reading:
open(FH, '<', $file) or die $!";
while ($line = <FH>) { # a way to read all lines (including a newline!) sequentially
print($line);
}
close(FH);
You can read the entire file and assign the contents to an array (although I do not recommend this):
open(FH, '<', $file) or die "$!";
@contents = ; # read all lines (with newline!) into an array (which can exceed your system's memory! So a bit tricky!)
print("@contents\n");
close(FH);
To append data at the end of the file, use:
open(FH, '>>', $file) or die "Could not open file '$file' $!"
print(FH "a new line added...\n"); # notice the newline character
close(FH);
You should -good programming style- close when you've opened a file (however, Perl does that for you automatically, if you forgot this).

8.4 Reading and replacing the contents of a file

You've to do four steps: reading the contents, writing this to a new file, rename the new file to the old filename and delete the new file:
$file_orig = "names.txt"
open(FH1, '<', $file_orig) or die "Could not open file $file_orig $!";
$file_new = "names_new.txt"
open(FH2, '>', $file_new) or die "Could not open file $file_new $!";

while (my $line = <FH1>) {
chomp $line; # chomp removes the newline character
$line = uc($line) . "\n"; # uppercase all lines
print(FH2 $line);
}
close(FH2);
close(FH1);
Rename names_new.txt into names.txt:
rename($file_new, $file_orig); || die ("unable to rename '' to ''");
... delete names_new.txt
unlink($file_new); || die ("can not unlink ''");

8.5 Create a subdirectory, create a file and write into it.

This does not work if 'subdir' does not exist:
open(FH, '>', "subdir/test.txt) or die "Could not open file $!";
Make first your directory:
$dir = "/home/reinier/subdir";
mkdir( $dir ) or die "Couldn't create $dir directory, $!";
print("Directory created successfully");
Create a file and write into it.
$file = "/home/reinier/subdir/test.txt";
open(FH, '>', $file) or die "Could not open file '$file' $!";
print(FH "testdata\n");
close(FH);

8.6 List files

@files = glob('*.*'); # *.* refers to all files; *.txt refers to all files with the extension '.txt'
print($_ . "\n") for (@files);

Exit: does a file exist (and if so, does it contain data)?

In the above code it was better to check if a file exists before operating on it. This can be done with the switch -e
$file = "/home/reinier/subdir/test.txt";
if (-e $file) ... etc.
Still better to check if a file exists and if it contains data:
$file = "/home/reinier/subdir/test.txt";
if (-z $file) ... etc.; # $file exists but is empty