Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

file handling in subroutines

Status
Not open for further replies.

rvBasic

Programmer
Oct 22, 2000
414
BE
I have a main program that could open an error log file.
That program calls a subroutine with the file handle as one of the optional arguments.

What I like to do in the subroutine is as follows:

- If the argument does not exist, use STDOUT as a log file
- If the argument exists, check if the file is open. If it is, use it. If it is not open, then open it (append) and use it.

The problems I have to implement this are essentially:
- How can I check if a file is open?
- Can I have something like:
print $FH, "xxx";
where $FH is either STDOUT or the FileHandle that was passed as an argument?



_________________________________
In theory, there is no difference between theory and practice. In practice, there is. [attributed to Yogi Berra]
 
maybe not the best way.. but it works

Code:
chomp @ARGV;
if ($ARGV[0]) {
	open(LOG, ">>$ARGV[0]") or die "can't open $ARGV[0]\n";
	$OUT = LOG;
}
else {
	$OUT = STDOUT;
}


print $OUT "Test\n";

close $OUT;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
two remarks:

- you are probably passing the filename as an argument. I would have preferred a file handle (the file could be already opened by the main program)
- use strict considered LOG and STDOUT as barewords.

_________________________________
In theory, there is no difference between theory and practice. In practice, there is. [attributed to Yogi Berra]
 
A strict-safe alternative:
Code:
chomp @ARGV;
my $OUT;
if ($ARGV[0]) {
    open($OUT, ">>$ARGV[0]") or die "can't open $ARGV[0]\n";
}
else {
    $OUT = *STDOUT;
}


print $OUT "Test\n";

close $OUT;
 
Thanks for your replies. I finally managed to get the following code almost to work:
Code:
#!/usr/bin/perl
use strict;

my $MyTestFile = 'C:\Perl\TestFile.txt';
my $LogFile = 'C:\Perl\MSGLOG.txt';

my $LOGH = undef;

#Entering a First time - write to standard log
&C($MyTestFile,'XXX',2);

#Entering a Second time - write to predefined log file
open ($LOGH, '>>', $LogFile);
print $LOGH "\nEntering Sub\n";
&C($MyTestFile,'XXX',2,*$LOGH);
print $LOGH "Quiting Sub\n";
[COLOR=red]close $LOGH;[/color]

#Entering a Last time - write to standard log
&C($MyTestFile,'XXX',2,*$LOGH);


sub C {
my $LOG=undef;
my ($Source,$Target,$Mode,$LogFile)=@_;
if ($LogFile){$LOG=$LogFile;
print $LOG "Message to existing log\n";
}
else{
$LOG=*STDOUT;
print $LOG "Message to standard log\n";
}
}
As I said: it almost worked! Of course it bumped on the third call, because I closed the File. But part of the file handle seems to subsist. Is there a possibility within the sub to check if the filehandle is closed?

I prefer not to use the Filename as an argument to the sub, because eventually this sub will go into a package module and I want it to be as independent as possible. I then also realized that I have to drop my initial requirement to open the file from within the sub. Without filename, no open.

So I settled to the simplified requirement: is there an opened log then use it, otherwise go to STDOUT. But there seems to be no simple way to verify if there exists an opened logfile. Or is there?

_________________________________
In theory, there is no difference between theory and practice. In practice, there is. [attributed to Yogi Berra]
 
Take a look at other code that works with filehandle references and see how they work. A lot of cryptography modules do this (the one that comes to mind is Crypt::CipherSaber).
Relevant bit of code:
Code:
sub fh_crypt
{
	my ( $self, $in, $out, $iv ) = @_;

	for my $glob ($in, $out)
	{
		my $reftype = reftype( $glob ) || '';
		unless ($reftype eq 'GLOB')
		{
			require Carp;
			Carp::carp( 'Non-filehandle passed to fh_crypt()' );
			return;
		}
	}

	local *OUT = $out;
	if ( defined($iv) )
	{
		$iv = $self->_gen_iv() if length($iv) == 1;
		$self->_setup_key($iv);
		print OUT $iv;
	}

	my $state = $self->[1];

	my ( $buf, @vars );

	while (<$in>)
	{
		unless ($iv)
		{
			( $iv, $_ ) = unpack( "a10a*", $_ );
			$self->_setup_key($iv);
		}
		my $line;
		( $line, $state, @vars ) = _do_crypt( $state, $_, @vars );
		print OUT $line;
	}
	$self->[1] = [ 0 .. 255 ];
	return 1;
}

-------------
Cuvou.com | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
Thanks Kirsle for guiding me in the right direction. I had a hard time to understand the code you supplied, but by googling for reftype, I hit in the same package upon the function openhandle that does exactly what I want: If the handle is open it supplies a reference to it, otherwise it returns undef.

The final code then was easy (as always if you know the solution)

Code:
#!/usr/bin/perl
use strict;

my $MyTestFile = 'C:\Perl\TestFile.txt';
my $LogFile = 'C:\Perl\MSGLOG.txt';

my $LOGH = undef;

#Entering a First time - write to standard log
&C($MyTestFile,'XXX',2);

#Entering a Second time - write to predefined log file
open ($LOGH, '>>', $LogFile);
print $LOGH "\nEntering Sub\n";
&C($MyTestFile,'XXX',2,*$LOGH);
print $LOGH "Quiting Sub\n";
close $LOGH;

#Entering a Last time - write to standard log
&C($MyTestFile,'XXX',2,*$LOGH);


sub C {

[COLOR=blue]use Scalar::Util qw(openhandle);[/color]

my $LOG=undef;
my ($Source,$Target,$Mode,$LogFile)=@_;
if ([COLOR=blue]openhandle($LogFile)[/color]){$LOG=$LogFile;
print $LOG "Message to existing log\n";
}
else{
$LOG=*STDOUT;
print $LOG "Message to standard log\n";
}
}

Thanks again to anyone who spent time and effort on this nasty problem!

_________________________________
In theory, there is no difference between theory and practice. In practice, there is. [attributed to Yogi Berra]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top