CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Using variables for file handle

 



hacksics
Novice

Jan 20, 2009, 2:26 AM

Post #1 of 13 (1591 views)
Using variables for file handle Can't Post

Hi I want to use a variable for a filehandle. See the below code


Code
my $FH = "FILE"; 
open($FH, ">$file_name");


this works if use strict is not in used. Any suggestions?

Thanks!


hacksics
Novice

Jan 20, 2009, 2:53 AM

Post #2 of 13 (1590 views)
Re: [hacksics] Using variables for file handle [In reply to] Can't Post

By the way I found this helps,

Code
no strict 'refs';


But I'm not sure its the correct way!


FishMonger
Veteran / Moderator

Jan 20, 2009, 5:18 AM

Post #3 of 13 (1585 views)
Re: [hacksics] Using variables for file handle [In reply to] Can't Post

No, that's not how you want to do it.

Remove this line:
my $FH = "FILE";

and do this:
open my $FH, '>', $file_name or die "Can't open '$file_name' $!";


hacksics
Novice

Jan 20, 2009, 8:47 AM

Post #4 of 13 (1583 views)
Re: [FishMonger] Using variables for file handle [In reply to] Can't Post

Sorry, I dont quite understand. If I do that, how to assign a value to $FH, if it is declared when opening a file handle?

What I want is, assign a file handle name to variable and used it throughout the script. Suppose I want to have two file handles like this


Code
my $FH = ""; 
$FH = "FIRST_FILE";
open $FH, '>', $first_file_name;
# do something with the file

$FH = "SECOND_FILE";
open $FH, '>', $second_file_name;
# do something with the second file



FishMonger
Veteran / Moderator

Jan 20, 2009, 9:16 AM

Post #5 of 13 (1582 views)
Re: [hacksics] Using variables for file handle [In reply to] Can't Post

Before I explain why you shouldn't do it that way, can you explain why you want or feel the need to do it that way?


hacksics
Novice

Jan 20, 2009, 7:18 PM

Post #6 of 13 (1572 views)
Re: [FishMonger] Using variables for file handle [In reply to] Can't Post

I just wanted to write a module for log writing purposes. When I create a log writer objects, if I use the same file handle I guess it will be a problem if I write several log files in my program. Please find my module below


Code
package LogWriter; 

use strict;
no strict 'refs';

sub new
{
my($class) = $_[0];
my $self = {};

$self->{'FILE_NAME'} = $_[1];
my @arrTmp = split('/', $_[1]);
my($strFileHandleName) = split('\.', $arrTmp[$#arrTmp]);
$self->{'FILE_HANDLE'} = $strFileHandleName;

my $strDate = DateStr2();
$self->{'HEADING'} = "File name : $arrTmp[$#arrTmp]\n"
."Date Stamp: $strDate\n";
$self->{'DEBUG'} = "TRUE";
my @arrStack = ();
$self->{'STACK'} = \@arrStack;
$self->{'FUNC_CALL'} = {};
$self->{'FUNC_TAG'} = "00000";

bless($self, $class);
return $self;
}

sub LogHeading
{
my($self, $heading) = @_;
return $self->{'HEADING'} if (! $heading);

$self->{'HEADING'} = $heading;
return $heading;
}

sub LowLevelDebug
{
my($self, $debug) = @_;
return $self->{'DEBUG'} if (! $debug );

$self->{'DEBUG'} = $debug;
return $debug;
}

sub LogOpen
{
my($self) = @_;
my $Filename = $self->{'FILE_NAME'};
my $FileHandle = $self->{'FILE_HANDLE'};
chomp($FileHandle);

print "$Filename $FileHandle \n";

my $TimeNow = $self->DateStr2();

if (-e "$Filename")
{
`/usr/bin/mv $Filename $Filename.$TimeNow`;
}

if ( ! open($FileHandle, ">$Filename"))
{
print "\nERROR: Cannot open log file [$Filename]\n\n";
exit(1);
}

print $FileHandle $self->{'HEADING'};

}

sub DateStr2
{
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
my $DateStr = sprintf("%04d_%02d_%02d_%02d_%02d_%02d", ($year + 1900), ($mon + 1), $mday, $hour, $min ,$sec);
return $DateStr;
}

sub Tabs
{
my($self) = @_;
my $count = scalar(@{$self->{'STACK'}});
for (my $i = 1; $i < $count; $i++)
{
print $self->{'FILE_HANDLE'} ("\t");
}
}

sub NewLogTag
{
my($self, $FunctionName) = @_;

my $FH = $self->{'FILE_HANDLE'};
my @CallStack = @{$self->{'STACK'}};
my %LogTagVal = %$self->{'FUNC_CALL'};

push(@CallStack, "$FunctionName");

$self->Tabs();
print $FH ("[FUNC:$FunctionName]\n");
$self->Tabs();
print $FH ("[CTACK:Global");

foreach my $func (@CallStack)
{
print $FH (" >> $func");
}

print $FH ("]\n");
$self->Tabs();
print $FH ("{\n");

if ( ! defined $LogTagVal{"$FunctionName"})
{
$LogTagVal{"$FunctionName"} = 1;
}
else
{
$LogTagVal{"$FunctionName"} ++;
}

my $tempval = $LogTagVal{"$FunctionName"};
$self->{'FUNC_TAG'} = sprintf("FUNCALLNO:%04d", $tempval);
}

sub EndLogTag
{
my($self) = @_;
my $FH = $self->{'FILE_HANDLE'};
my @CallStack = @{$self->{'STACK'}};

$self->Tabs();
print $FH ("}\n");
pop(@CallStack);
}

sub Log
{
my($self, $text, $line) = @_;
my $FH = $self->{'FILE_HANDLE'};

chomp($text);
print $FH ("~|$line|$text\n");
}

sub LogText
{
my($self, $text, $line) = @_;
my $LogTag = $self->{'FUNC_TAG'};
my $FH = $self->{'FILE_HANDLE'};

my $TimeNow = $self->DateStr2();
$self->Tabs();
print $FH ("\t~$TimeNow [TEXT]|$LogTag|LINE:$line|$text\n");
}

sub LogWarn
{
my($self, $text, $line) = @_;
my $LogTag = $self->{'FUNC_TAG'};
my $FH = $self->{'FILE_HANDLE'};

my $TimeNow = $self->DateStr2();
$self->Tabs();
print $FH ("\t~$TimeNow [WARN]|$LogTag|LINE:$line|$text\n");
}

sub LogInfo
{
my($self, $text, $line) = @_;
my $LogTag = $self->{'FUNC_TAG'};
my $FH = $self->{'FILE_HANDLE'};

if($self->{'DEBUG'} eq "TRUE")
{
my $TimeNow = $self->DateStr2();
$self->Tabs();
print $FH ("\t~$TimeNow [INFO]|$LogTag|LINE:$line|$text\n");
}
}

sub LogError
{
my($self, $text, $line) = @_;
my $LogTag = $self->{'FUNC_TAG'};
my $FH = $self->{'FILE_HANDLE'};

my $TimeNow = $self->DateStr2();
$self->Tabs();
print $FH ("\t~$TimeNow [EROR]|$LogTag|LINE:$line|$text\n");
}

sub LogClose
{
my($self) = @_;
my $FH = $self->{'FILE_HANDLE'};
close($FH);
}



FishMonger
Veteran / Moderator

Jan 21, 2009, 6:12 AM

Post #7 of 13 (1556 views)
Re: [hacksics] Using variables for file handle [In reply to] Can't Post

Unless this is simply an academic exercise, I'd highly recommend using the proven and well written Log::Log4perl instead of what you currently have written.
http://search.cpan.org/~mschilli/Log-Log4perl-1.20/lib/Log/Log4perl.pm


hacksics
Novice

Jan 21, 2009, 5:51 PM

Post #8 of 13 (1549 views)
Re: [FishMonger] Using variables for file handle [In reply to] Can't Post

Thank you :)

But are there any alternatives available to overcome the "strict ref" error while using variables as file handle?


FishMonger
Veteran / Moderator

Jan 21, 2009, 6:08 PM

Post #9 of 13 (1547 views)
Re: [hacksics] Using variables for file handle [In reply to] Can't Post

Simple, don't assign a value to the var.

To conform to the restrictions of the strict pragma, variables used for filehandles need to be undefined when the filehandle is created. If the variable is defined with the my keyword, as it should be, the filehandle will automatically be closed when it goes out of scope.


FishMonger
Veteran / Moderator

Jan 21, 2009, 6:50 PM

Post #10 of 13 (1546 views)
Re: [hacksics] Using variables for file handle [In reply to] Can't Post

On a side note regarding your code, there are a couple issues you should be aware of.

This bit has 3 issues.

Code
if (-e "$Filename")  
{
`/usr/bin/mv $Filename $Filename.$TimeNow`;
}


You can learn about the first 2 issues by reading these FAQ.
perldoc -q quoting
perldoc -q "What's wrong with using backticks in a void context?"

Why use backticks to spawn a new process and make the script non portable when Perl has methods to rename the file in a portable manor?

The DateStr2 sub could be reduced and simplified by using the strftime function in the POSIX module.


hacksics
Novice

Jan 21, 2009, 11:02 PM

Post #11 of 13 (1542 views)
Re: [FishMonger] Using variables for file handle [In reply to] Can't Post


In Reply To
Simple, don't assign a value to the var.

To conform to the restrictions of the strict pragma, variables used for filehandles need to be undefined when the filehandle is created. If the variable is defined with the my keyword, as it should be, the filehandle will automatically be closed when it goes out of scope.


Thanks a million.

But If I define the FH as you explained I wont be able to access that FH from other sub routine right?


FishMonger
Veteran / Moderator

Jan 22, 2009, 5:23 AM

Post #12 of 13 (1533 views)
Re: [hacksics] Using variables for file handle [In reply to] Can't Post


In Reply To
But If I define the FH as you explained I wont be able to access that FH from other sub routine right?


What makes you think that?

You access it via the hash key, not the value of that key, which is what you're doing.

Here's a simple example.

Code
use strict; 
use warnings;

my $logfile = create_filehandle('/path/to/file.log');
writelog($logfile, 'this is a test messege');

sub create_filehandle {
my $FH = {};
open $FH->{filehandle}, '>>', $_[0] or die "can't open '$_[0]' $!";
return $FH;
}

sub writelog {
print { $_[0]->{filehandle} } "$_[1]\n";
}



hacksics
Novice

Jan 22, 2009, 7:47 AM

Post #13 of 13 (1530 views)
Re: [FishMonger] Using variables for file handle [In reply to] Can't Post

Thanks, Got the point :)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives