|
|
Perl File Handling: open, read, write and close files
This article describes the facilities provided for Perl file handling.
Opening files
Opening a file in perl in straightforward:
open FILE, "filename.txt" or die $!;
The command above will associate the FILE filehandle with the file
filename.txt. You can use the filehandle to read from the file. If
the file doesn't exist - or you cannot read it for any other reason - then
the script will die with the appropriate error message stored in the
$! variable.
What if you wanted to modify the file instead of just reading from it? Then
you'd have to specify the appropriate mode using the three-argument form of
open.
open FILEHANDLE, MODE, EXPR
The available modes are the following:
| mode |
operand |
create |
truncate |
| read |
< |
|
|
| write |
> |
✓ |
✓ |
| append |
>> |
✓ |
|
Each of the above modes can also be prefixed with the + character
to allow for simultaneous reading and writing.
| mode |
operand |
create |
truncate |
| read/write |
+< |
|
|
| read/write |
+> |
✓ |
✓ |
| read/append |
+>> |
✓ |
|
Notice, how both +< and +> open the file in read/write
mode but the latter also creates the file if it doesn't exist or truncates
(deletes) an existing file. So, if you wanted to open a file for writing,
creating it if it doesn't exist and truncating it first if does, you'd do
the following:
open FILE, ">", "filename.txt" or die $!
This operation might fail if for example you don't have the appropriate
permissions. In this case $! will be set appropriately.
The mode and the filename in the three-argument form can be combined, so
the above can also be written as:
open FILE, ">filename.txt" or die $!;
As you might have guessed already if you just want read access you can skip
the mode just as we did in the very first example above.
Reading files
If you want to read a text file line-by-line then you can do it as such:
my @lines = <FILE>;
The <FILE> operator - where FILE is a previously
opened filehandle - returns all the unread lines of the text file in list
context or a single line in scalar context. Hence, if you had a particularly
large file and you wanted to conserve memory you could process it line by line:
while (<FILE>) {
print $_;
}
The $_ variable is automatically set for you to the contents of
the current line. If you wish you may name your line variable instead:
while (my $line = <FILE>) { ...
will set the $line variable to the contents of the current line.
The newline character at the end of the line is not removed automatically.
If you wish to remove it you can use the chomp command. After all
lines have been read the <FILE> operator will return a false
value hence causing the loop to terminate.
There may cases where you need to read a file only a few characters at a
time instead of line-by-line. This may be the case for binary data. To do
just that you can use the read command.
open FILE, "picture.jpg" or die $!;
binmode FILE;
my ($buf, $data, $n);
while (($n = read FILE, $data, 4) != 0) {
print "$n bytes read\n";
$buf .= $data;
}
close(FILE);
There is a lot going on here so let's take it step by step. In the first
line of the above code fragment a file is opened. As you can guess from the
filename it is a binary file. Binary files need to treated differently than
text files on some operating systems (eg, Windows). The reason is that on
these platforms a newline "character" is actually represented
within text files by the two character sequence \cM\cJ (that's
control-M, control-J). When reading the text file Perl will convert the
\cM\cJ sequence into a single \n newline characted. The
converse also holds when writing files. Clearly, when reading binary data
this behavior is undesired and calling binmode on the filehandle
will make sure that this conversion is avoided. The read
command takes either 3 or 4 arguments. The 3-argument form is:
read FILEHANDLE, SCALAR, LENGTH
while the 4-argument form is:
read FILEHANDLE, SCALAR, LENGTH, OFFSET
In the first case LENGTH characters of data are read in the
variable specified by SCALAR from FILEHANDLE. The return
value of read is the number of characters actually read,
0 at the end of the file or undef in the case of an
error. Returning to our example above the third line of code will read at
most 4 characters of data into the $data variable. The number of
characters read will be stored in $n. Successive read operations
on the same filehandle will set the current file position to be just before
the first unread character. Thus the code above will read the contents of
the file picture.jpg and store them in $buf, printing the
number of characters read at every iteration.
If OFFSET is specified then the characters read will be placed at
that position within the SCALAR. Taking advantage of this we could
rewrite the loop above as such:
my ($data, $n, $offset);
while (($n = read FILE, $data, 4, $offset) != 0) {
print "$n bytes read\n";
$offset += $n;
}
Even though the example above demonstrates binary reading the read
command works just as well on text files - just make sure to use (for
binary) or not use (for text) binmode accordingly.
Writing files
Now that you know how to open and read files learning how to write to them
is straighforward. Take a look at the following code:
open FILE, ">file.txt" or die $!;
print FILE $str;
close FILE;
Not much is new here. The only thing to observe is the two-argument use of
print, the first argument being the FILEHANDLE to write
to and the second an expression to be written. The expression can be
anything: a scalar, a list, a hash, etc. Appending to a file can be
accomplished in exactly the same manner - apart from specifying the
appropriate (>>) mode of course.
At this point you are probably thinking that a description of the write
is what follows. Actually, as the manual page for write puts it:
Note that write is not the opposite of read. Unfortunately.
Instead write is used to write formatted records to file, a
subject outside the scope of this article.
Closing files
Once you are done reading and writing you should close any open filehandles.
open FILE1, "file.txt" or die $!;
open FILE2, "picture.jpg" or die $!;
...
close FILE2;
close FILE1;
If you forget to close a filehandle Perl will do it for you before your
script exists but it is good practice to close yourself what you have
opened.
The close command may also fail returning false, eg, if
you try to close a closed filehandle. If you want to catch these errors you
can check the return value of close and the approriate error
message stored in $! as is done in the following example:
close FILE or die $!
Summary of perl file handling
The open, close, print and read
commands will allow you to perform most common file operations. However,
much more is possible. Apart from opening files you may open pipes to other
commands using the | mode and read from them or write to them
using the techniques described. This and more in an article to come.
Comments
|
David | Posted at 6:38am on Tuesday, June 26th, 2007 | Cool tutorials but the perl installation file. havidworld@yahoo.co.nz |
fountain_spray | Posted at 12:50pm on Wednesday, June 27th, 2007 | Not describing Format for Write is a cop-out!
Where do I turn for THAT tutorial? |
Richard Wicks | Posted at 4:11pm on Thursday, August 23rd, 2007 | Well, great, I can read binary files now. How the heck do I write them? |
Tobias Maier | Posted at 7:13am on Thursday, August 30th, 2007 | You can use 'pack' to write binary files.
E.g.: The following snippet writes all numbers between 0 and zero as unsigned characters.
open(BIN, '>', 'binary_file')
or die "Couldn't open file for writing: $!n";
foreach my $i (0 ... 255) {
print BIN pack('C', $i);
}
close BIN; |
Jo | Posted at 9:09am on Monday, September 24th, 2007 | I need to be able to read the first 20 lines of a txt file. How about that.
@ARGV? |
Richard | Posted at 2:57pm on Tuesday, September 25th, 2007 | open(FILE, " |
Richard | Posted at 2:59pm on Tuesday, September 25th, 2007 | open(FILE, " |
Richard | Posted at 3:00pm on Tuesday, September 25th, 2007 | Sorry, I don't know why it won't take my entire comment :( |
Sasi | Posted at 9:25am on Monday, October 1st, 2007 | I have a hash variable with 10K records and I want to write 1000 records at one shot into the file. Is there a way in perl? |
Clement | Posted at 1:42pm on Monday, October 1st, 2007 | Thanks for this site, it is really good. If I want to read several files such as c_1, c_2, c_3 etc in the same directory, how do I write the perl script to do this for me. Please, you could send me a response to agclems@yahoo.com Many thanks for your help.
Regards,
Clement. |
Salvor | Posted at 12:47am on Tuesday, October 23rd, 2007 | I think it's better to write here and not send you a private response. Anyelse can read it, so:
my $i=1;
while (-e "c_$i"){
open (FILE, "c_$i") || die ("What the hell??? Can't open c_$i!!!");
my @lines = ;
close FILE;
doincrediblethingswhiththe(@lines);
$i++;
} |
Salvor | Posted at 12:50am on Tuesday, October 23rd, 2007 | Sorry, the forum eat some of my comment. 4th line:
my @lines = <FILE>;
well, you know, read all file into an array, as explained before in this page.
Regards. |
Norton | Posted at 7:13am on Wednesday, November 21st, 2007 | I would really like to see how can you store the contents of the file in an array, where lines are appended as array elements.
Could you please add it to this tutorial?
Cheers, Norton |
Johan | Posted at 4:17am on Friday, December 7th, 2007 | Norton: to add a file to an array,
@array = ;
should do the trick. |
harsh | Posted at 8:55am on Thursday, December 13th, 2007 | read multiple files from same directory
opendir DIR, "C:/perl/bin/1" || die "Cannot opendir 1 $!";
while ( $filename = readdir(DIR) ) {
if($filename=~/.*.htm/){
open IN, "C:/perl/bin/1/$filename";
open OUT,">>C:/perl/bin/1/all.txt";
while(){ chomp ($_);
and so on}
by using this you can read multiple files from directory 1 and write all the files in a new file.
regards
harsh |
Jared | Posted at 9:19am on Wednesday, December 19th, 2007 | This:
foreach my $i (0 ... 255) {
print BIN pack('C', $i);
}
Could also be written as:
print BIN map(pack($_),@{[0..255]});
:) |
cris | Posted at 10:37am on Wednesday, December 26th, 2007 | how do you open a image and print it? |
Nikhil | Posted at 2:52pm on Saturday, December 29th, 2007 | How do you search for a pattern and then delete all the lines above and below it?
eg
abbbbbbbbbcioiheiodnweiniwqoed
Serial Number
iuawheiuhoiehoqwiheeewq
I want to search for Serial Number and delete all three lines..
I want to repeat this all over the file wherever the Serial Number occurs.. |
kumar | Posted at 12:06pm on Thursday, January 3rd, 2008 | I need a script for the below task.I have a txt file with xxxxx numbers , one number each line.
I should run a perl script so that my script should read this txt file line 1 and then line 2 , then line 3 etc till the predefined match is found.I wanna use this line 1 value in the command executed below this script.this command output should be updated to a new file always.
Obiliged if any answers for my query. |
SK Rahman | Posted at 4:49am on Friday, January 4th, 2008 | if i run the following script i am getting a binary file
but when i open with hex editor
i am able see that the actual numbers are
"01 02 03 04 05 06 07 08 09"
what i wanted output like this
"12 34 56 78"
please help me to write a script for this...
thanks in advance
open(BIN, '>', 'binary_file')
or die "Couldn't open file for writing: $!n";
foreach my $i (1 ... 9)
{
binmode BIN;
print BIN pack('C', $i);
}
close BIN; |
ZwribMaster | Posted at 6:39pm on Thursday, January 17th, 2008 | Hi, I want to try to open a file, and if it fails, I want to write the filename to a log file but continue on with my program to open the other files in my list. Is there an alternative to using open the file || or die? |
ZwribMaster | Posted at 6:52pm on Thursday, January 17th, 2008 | Hi Nikhil,
You can read the file contents into an array, and then use a foreach loop to scan each line of the array. For ex:
open(PAGE,"yourfile.txt") || die "I can't open yourfile.txt";
#store the contents of the file into the File array
@File = ;
close(PAGE);
$Ctr = 0;
#then loop through the file...
foreach (@File){
if ($File[$Ctr] =~ m/SerialNumber/){
#remove the 3 lines from the array
$File[$Ctr] = "";
$File[$Ctr+1] = "";
$File[$Ctr-1] = "";
}
$Ctr = $Ctr+1; #increment through the rest of array
} #end foreach
#write the array contents to the file...
open(PAGE,">yourfile.txt") || die "I can't open yourfile.txt"; #open the file to read
print PAGE @File;
close(PAGE); |
Dave | Posted at 8:51am on Sunday, January 20th, 2008 | I'm trying to load a txt file into an array and filter out specific data. I used ZwribMaster post as a template and it has helped a lot. I have one issue. Instead of removing the lines from the array, it is just replacing them with a blank space. Here is sample of what I'm running:
#Open and Load Input file to array
open INPUT_FILE, "data.txt" or die $!;
print OUTPUT_FILE "@Data";
close OUTPUT_FILE;
Any help would be appreciated,,
Thanks,
Dave C |
DaveC | Posted at 11:24am on Sunday, January 20th, 2008 | It's seems my script was cut off in my last post.
#Open and Load Input file to array
open INPUT_FILE, "data.txt" or die $!;
print OUTPUT_FILE "@Data";
close OUTPUT_FILE; |
Sai Ram | Posted at 9:52pm on Monday, January 21st, 2008 | How to make use oF APIs in perl..please help me out...i am lost becoz of this.. :-(
I need this immediately... |
Sylvia | Posted at 8:05am on Tuesday, January 29th, 2008 | Hi there!
I would like to print the same content to 4 output files at the same time, is there anyway to do this, or do I have to do it on four separate lines?
eg
print FILE_1 "example";
print FILE_2 "example";
print FILE_3 "example";
print FILE_4 "example";
can I do something like this?
print {FILE_1 FILE_2 FILE_3 FILE_4} "example";
thanks for your help |
Kiran | Posted at 2:24am on Friday, February 1st, 2008 | Hi Friends!! I need to write a script which will logon to sftp server & then check for files in a particular directory if the file is present it should append that file is present ina text file if not it should append file not present how this can be achieved i am stuck up at logging on to sftp server please help thanks in advance |
Kiran | Posted at 11:23pm on Wednesday, February 13th, 2008 | Hi,
I have 2 files, say file1 & file2. I have some, variable in file1 say $work. I want to read this in file2 & use it in file2.
Could anyone help me in this
Thanks
Kiran |
Rich | Posted at 8:39pm on Saturday, February 23rd, 2008 | Kiran, regarding your question on the thirteenth, simply open both files, and copy the $work to file2. |
Kiran | Posted at 2:46am on Monday, February 25th, 2008 | Guys can any body help me on question posted on 1st feb 08
" need to write a script which will logon to sftp server & then check for files in a particular directory if the file is present it should append that file is present ina text file if not it should append file not present how this can be achieved i am stuck up at logging on to sftp server please help thanks in advance" |
Torsten | Posted at 3:17am on Friday, March 14th, 2008 | Hi,
I have the following problem:
I want to open a file and read its content into a variable.
After that a standard input should be read into another variable. But after this input, the script gets stuck.
If I swap both, the script works. Here a part of my script:
open FILE, "c:/tmp/mail_receivers.txt" or die "Couldn't open: $!";
local $/;
$receiver = ;
close FILE;
print ("nPlease enter mail subject.");
$subject = ;
print ("nSubject: $subject");
print("$receiver");
Can anybody help me?
Thanks,
Torsten |
Bassir | Posted at 11:23pm on Sunday, March 16th, 2008 | i have too many problems with doing an algorithm |
Manojg | Posted at 11:23am on Wednesday, March 19th, 2008 | Hi,
I tried to open a file by using
open FILE, ">", "filename.txt" or die $!
The script did not give any error and there was no any file opened. Where does it open the file? in memory? How do I open a file in disk?
Thanks. |
Shruthi | Posted at 1:12am on Monday, March 24th, 2008 | How do i write perl script for reading a file and how i can see output from this.
If any body knows please send it back as comments in this same page. |
Suresh,S | Posted at 1:44am on Monday, March 24th, 2008 | created a excel sheet as Book1.xls
just tried this coding for opening Book1.xls unable to open the excel file the output is coming in Dos prompt itself why?
#!/usr/local/bin/perl
open (MYFILE, 'Book1.xls');
while () {
chomp;
print "$_n";
}
close (MYFILE);
Just reply the solution Immediately |
Jacob | Posted at 11:24am on Wednesday, April 2nd, 2008 | Hi all..
Im trying to make this littel hash cracker in perl (JTR dosent take saltet hash), and it works fine, but now i want it to goto next hash, when it finds a correct password, insted of trying the intire paasword list.. (aka for more speed)
The script looks like this:
#!/usr/bin/perl
use Digest::MD5 qw(md5_hex);
use Data::Dumper;
open(FH0, " < digits"); #long list of passwords
while(){
chomp;
($password,$b) = split(/:/);
open(FH1, "< alle1"); #long list of hash
while() {
chomp;
($last,$hash,$salt,$mail) = (split(/:/))[0,1,2,3]; {
open (FH2, '>>data.txt');
print FH2 "$mail:$passwordn" if(md5_hex($salt.$password) eq $hash);
# print "BINGO CHAMPn" if(md5_hex($salt.$password) eq $hash);
# print "$passwordn";
}
}
}
close(FH0);
close(FH1);
close(FH2);
Can someone help me whit that? |
Pramod Badgujar | Posted at 10:17pm on Tuesday, April 8th, 2008 | How to replace the content of line with the another text? |
Pramod Badgujar | Posted at 10:22pm on Tuesday, April 8th, 2008 | How to replace the content of line with the another text?
Please give me answer of the above question. |
emma | Posted at 9:10am on Friday, April 11th, 2008 | Hi all,
I am new to Perl scripting and need your help.
Here is the problem I am having .
I have a file with some strings each delimited by a "|'character.
I have to open the file , each each line and replace the '|' with a tab or space and then copy them to to a file.
Eg: file ABC
Contents are as follows -
asdfd|||sdhh||sdghhgd|||
afsgasfd||asdsadsad|adff||||||fasffasf|
etc
Desired output
asdfd sdkjf dsfhdh
sffhjd djfhjhds dhfjhfjh (ie no "|" characters.)
I appreciate your help.
Please some one help me with the perl code to do this task . I am sure it is easy job for perl experts. |
Bharath | Posted at 6:42pm on Monday, April 21st, 2008 | Hi,
I want to open an image and see the binary values of that image.Is there a way to open an jpeg or png or bmp file and prints the contents of that file in zeroes and ones using perl.
Thanks in advance,
Bharath |
reddy | Posted at 3:00pm on Tuesday, April 29th, 2008 | Does anybody answer here or just post Q's? |
The bumbling bee | Posted at 12:44pm on Saturday, May 10th, 2008 | Hi Emma,
Can the following piece of code do?
$fileName = "ABC";
open(FILE," |
The bumbling bee | Posted at 12:48pm on Saturday, May 10th, 2008 | The bumbling bee
Hi Emma,
How do I avoid the "eating" of comments after the "<" glyph? |
The bumbling bee | Posted at 12:52pm on Saturday, May 10th, 2008 | Ok, trying one more time!
$fileName = "ABC";
open(FILE,"< $fileName") or die "Could not open file $fileName";
while ($line = < FILE> ) {
$line =~ s/|+$//; ## **1 (see below)
$line =~ s/|+/ /g; ## **2 (see below)
print $line;
}
close(FILE);
## BRIEF EXPLANATION:
## ------------------
## The command "s/+++/***/" substitute "+++" with "***".
## The "|+" is regular expression matching one or more
## consecutive "|" chars.
##
##
## EXPLANATION OF "**1":
## The regular expression "|+$" requires one or more
## consecutive "|" chars at the end of the line since
## "$" match end-of-line. This is replaced by nothing.
##
## EXPLANATION OF "**2":
## The regular expression "|+$" requires one or more
## consecutive "|" as before. This is replaced by a
## single space.
## The option "g" (global) in the end indicates, that
## several sequences may be replaced if such exist.
## |
beta32c | Posted at 12:22am on Thursday, May 15th, 2008 | Can we open files which are more than 2gb in size. Im not able to open my files for processing which are more than 2gb.. any ways.. reply back. |
kumar | Posted at 8:50am on Tuesday, May 20th, 2008 | I have a file which the format is ".dat". I would like to read the information from this file and convert all the information to txt format. Is the perl able to do this. |
Joe | Posted at 6:51am on Friday, May 30th, 2008 | what drives me nuts about many perl people offering suggestions is they offer squat. Try using this,try using that. For newbies this is no help at all. Explain it or don't bother offering suggestions. I keep seeing tons of people posting things like try this in your code. Suppose the person asking doesn't even know how to begin let alone put the code in the proper place in the script. Suppose the person has spent hours trying to figure it out and just wants some help and needs the entire script. Get real posters. I'm fed up with those who don't post the complete solution. |
Newbies - start here | Posted at 9:56am on Friday, June 13th, 2008 | A lot of you are asking questions that are hard to answer if you don't know hardly anything about perl. Teach yourself the basics here: http://www.pageresource.com/cgirec/index2.htm. Or search google for beginning perl tutorial. There are many books as well. To try to help some of you, here is a full working script that will read a file in, process the file and save it to a new file. The files will be in the same folder as the perl script. This will overwrite your output file each time you run it.
#!/usr/bin/perl -w
use strict;
my $infile = 'in.txt'; # name of the file you are reading - must be in same folder as script
my $outfile = 'out.txt'; # name of file that will be created for output
open (FILEHANDLE, '' will create the file if necessary
# WARNING: this will overwrite your $outfile if it exists - copy to new file if you want to save what you have in your output file
print OUT $outdata; # write the data - will overwrite whatever you had in the output file previously
close OUT; # close the file
exit; # you are done |
Anonymous | Posted at 10:14am on Friday, June 13th, 2008 | OK. One last try with the HTML characters escaped. (In fact, I escaped the characters, like <> using my script below)
A lot of you are asking questions that are hard to answer if you don't know hardly anything about perl. Teach yourself the basics here: http://www.pageresource.com/cgirec/index2.htm. Or search google for beginning perl tutorial. There are many books as well. To try to help some of you, here is a full working script that will read a file in, process the file and save it to a new file. The files will be in the same folder as the perl script. This will overwrite your output file each time you run it.
#!/usr/bin/perl -w
use strict;
my $infile = 'in.txt'; # name of the file you are reading - must be in same folder as script
my $outfile = 'out.txt'; # name of file that will be created for output
open (FILEHANDLE, '<', $infile); # this makes the file ready for reading from FILEHANDLE
# '<' means read only
my @inlines; # this is an array. An array holds a list of items. Each list item will be 1 line from the input file
@inlines = <FILEHANDLE>; # this reads the input file into the array - each array item holds 1 line of the file
my @outlines; # we will put the output lines here
#we're done reading the file - close it
close FILEHANDLE;
foreach my $line (@inlines) { # this cycles through the input file info 1 line at a time
chomp($line); # remove newline character at end of line
# I will show a few examples of what you can do to process each line
# just uncomment the code (remove the # in front of the code) to use what you want
# # change all '|' characters to tabs
# $line =~ s/\|/\t/g;
# # separate each word - one word per line - changes whitespace (spaces, tabs, etc) to new lines
# $line =~ s/\s+/\n/g;
# # replace the line with new content
# $line = "Goodbye my friend." if ($line =~ /^Hello everyone!$/); # if the line said 'Hello everyone!', now it will say 'Goodbye my friend.'
# # replace a word with another
# my $search_word = 'aks';
# my $replace_word = 'ask';
# $line =~ s/$search_word/$replace_word/gi; # g replaces all occurances, i makes it case insesitive - matches lower case and upper case
# url encode the line to make it safe for posting, so that < characters won't mess it up (such as for the comments at http://www.perlfect.com/articles/perlfile.shtml)
# $line =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
#escape HTML Characters "<", ">", "&" etc.
$line =~ s/([^\w\s])/sprintf ("&#%d;", ord ($1))/ge;
# put the line in the output array
push(@outlines,$line);
}
# join the output lines into one variable with a newline character between each line
my $outdata = join("\n",@outlines);
# save $outdata to the $outfile
open (OUT,">", $outfile); # this will open the $outfile for writing, and '>' will create the file if necessary
# WARNING: this will overwrite your $outfile if it exists - copy to new file if you want to save what you have in your output file
print OUT $outdata; # write the data - will overwrite whatever you had in the output file previously
close OUT; # close the file
exit; # you are done |
hiru.. | Posted at 2:38am on Wednesday, June 18th, 2008 | i want to write an array into a textfile. i m using active perl in windows xp.... |
noor | Posted at 11:57pm on Wednesday, June 18th, 2008 | how to delete a portion or couple lines from the file basically text file |
Anonymous | Posted at 5:05am on Thursday, July 3rd, 2008 | i have one already open file . please tell how to delete the 4 th line . again i needto addd differnt data to fil |
Barney | Posted at 2:58pm on Friday, July 4th, 2008 | I want to manually process many text files as follows:
myscript.pl file1.txt
myscript.pl differentfilename.txt
I am able to read the file into an array as follows:
my @INFILE = ;
But I don't know how to get the filenames to uniquely assign output files (ie. file1_out.txt, differentfilename_out.txt)
Thanks in advance. |
Comments to date: 53.
|
Suggested Reading
|