Reputation:
OK, so this is so simple but for the life of me I can't figure out why the code below doesn't work.
I'm trying to simply write a CGI script that creates sequentially numbered files. I'm using a counter (stored in a separate file) to keep track of the last ordinal used, and then generating a unique filename using sprintf
. The uniquely named file is NOT created. I suspect it's an issue with sprintf(...)
not correctly converting $ordinal to a scalar?
If I assign $ordinal
by say replacing the line $ordinal = <NUMPHOTOS>;
with $ordinal=42;
the code works fine and a file named 00000042.jpg
is created.
What am I doing wrong here?
Help!
my ($filename, $ordinal);
local $| = 1;
print "Content-type: text/plain\n\n";
# NOTE: $ordinal is set to zero if the file doesn't exist
open (NUMPHOTOS, "<numpics.dat");
$ordinal = <NUMPHOTOS>;
print "ordinal = $ordinal";
$filename = sprintf("%08d.jpg", $ordinal );
close (NUMPHOTOS);
open (NUMPHOTOS, ">numpics.dat");
$ordinal += 1;
print NUMPHOTOS $ordinal;
close (NUMPHOTOS);
open ( UPLOADFILE, ">$filename" ) or die "ERROR: can't open $filename: $! \n";
print "writing out file $filename...\n";
print UPLOADFILE 'hello world';
close UPLOADFILE;
Upvotes: 0
Views: 2117
Reputation: 34110
Here is my attempt to fix up your program.
I think your problem was the lack of chomp()
;
use strict;
use warnings;
use autodie; # don't need to check the return value of open() or close()
my( $filename, $ordinal );
local $| = 1;
print "Content-type: text/plain\n\n";
# NOTE: $ordinal is set to zero if the file doesn't exist
{
open( my $num_photos, '<', 'numpics.dat' );
$ordinal = <$num_photos>;
chomp $ordinal; # <--
print "ordinal = $ordinal\n";
$filename = sprintf("%08d.jpg", $ordinal );
print "filename = $filename\n";
close ($num_photos);
}
{
open( my $num_photos, '>', 'numpics.dat' );
$ordinal += 1;
print {$num_photos} $ordinal;
close( $num_photos );
}
{
open( my $upload_file, '>', $filename );
print "writing out file $filename...\n";
print {$upload_file} 'hello world';
close $upload_file;
}
Note that this still doesn't attempt to resolve locking problems. So if this needs to be atomic, you may want to ask another question
Upvotes: 0
Reputation: 369
Is there a newline in the file? What happens to $ordinal if you change:
$ordinal = <NUMPHOTOS>;
to
<NUMPHOTOS> =~ /(\d+)/ and $ordinal = $1;
?
Upvotes: 0
Reputation: 1366
Upvotes: 0
Reputation: 8972
As everybody mentioned, you should:
Use strictures --
use strict;
use warnings;
use diagnostics; # will help you understand the error messages
Check the file name, the current directory and the permissions on writing the filename;
Use the 3-parameter open, and lexical filehandles, AND check the operations --
open my $uploadfile, '>', $filename or die "could not open $filename: $!";
print $uploadfile "Hello, uploadfile!\n" or die "could not print at $filename: $!";
close $uploadfile or die "could not close $filename: $!";
Upvotes: 1
Reputation: 7394
First add "use strict;use warnings;use diagnostics;use Fatal qw/:void open close/;" at start of your code, after #!.
my $ordinal=0;
if (-e 'numpics.dat') {
open (my $NUMPHOTOS, "<","numpics.dat");
$ordinal = <$NUMPHOTOS>;
close ($NUMPHOTOS);
}
print "ordinal = $ordinal\n";
my $filename = sprintf("%08d.jpg", $ordinal );
Also it is a good idea to read Ovid's CGI Course.
Upvotes: 3
Reputation: 26910
Perl have no problem sprintf()
a string-number --- it is not strongly typed.
Make sure you have the permission to create files with CGI. Some web hosting require chmod 755
on the directory you write.
Upvotes: 1