pem@frankland-river.aaii.oz.au (Paul E. Maisano) (02/05/90)
I was wondering what sort of object a filehandle was and what can be done with one besides printing to them etc. Specifically, can you save them in a local context in some way, similar to what the local() function does with variables. For example, if I open a file in a subroutine and use a file handle called FILE which I open and then close, how do I know I'm not stomping on another filehandle called FILE which has already been opened somewhere else in my program. I could create a package to avoid the possibility of a naming conflict but this does not really solve the problem. What if I want to write a recursive subroutine which opens a file ? How do I keep separate filehandles for each recursive call ? Is there a simple way to do this or must I generate a unique filehandle name on each invocation ? Any ideas appreciated. ------------------ Paul E. Maisano (email: pem@aaii.oz.au) Australian Artificial Intelligence Institute 1 Grattan St. Carlton, Vic. 3053, Australia Ph: +613 663-7922 Fax: +613 663-7937
rae%alias@csri.toronto.edu (Reid Ellis) (02/07/90)
pem@frankland-river.aaii.oz.au (Paul E. Maisano) writes: |... if I open a file in a subroutine and use a file handle called |FILE which I open and then close, how do I know I'm not stomping on |another filehandle called FILE which has already been opened somewhere else |in my program. | | ... | |Is there a simple way to do this or must I generate a unique filehandle name |on each invocation ? Don't forget that you can use variables for filehandles. I ran into the recusion problem myself and found that you couldn't have "local" filehandles, so the way I got around this was as follows: $input = "recursion00"; sub recur { $input++; open($input, "filename"); if(condition) { &recur(); } close($input); $input--; } Or something along those lines.. This will give you filehandles with names like recursion01, recursion02, recursion03 etc. Note that I wrote the above off the top of my head, but you get the idea. Reid --- "I don't even know what street Canada is on" -- Al Capone Reid Ellis 264 Broadway Avenue, Toronto ON, Canada M4P 1V9 rae%alias@csri.toronto.edu || +1 416 487 1383 "I don't even know what street Canada is on" -- Al Capone Reid Ellis 264 Broadway Avenue, Toronto ON, Canada M4P 1V9 rae%alias@csri.toronto.edu || +1 416 487 1383
lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/08/90)
In article <1004@frankland-river.aaii.oz.au> pem@frankland-river.aaii.oz.au (Paul E. Maisano) writes: : I was wondering what sort of object a filehandle was and what can be done : with one besides printing to them etc. : : Specifically, can you save them in a local context in some way, similar to : what the local() function does with variables. : : For example, if I open a file in a subroutine and use a file handle called : FILE which I open and then close, how do I know I'm not stomping on : another filehandle called FILE which has already been opened somewhere else : in my program. : : I could create a package to avoid the possibility of a naming conflict but : this does not really solve the problem. I believe you can do a local on a name using the type globbing syntax: sub foo { local(*FILE); open(FILE,'foo'); etc. I haven't exercised it heavily, but the code is supposedly there to create a new name if you aren't assigning another name to *FILE. Just as normal variables created with a null value when you don't assign something to them. : What if I want to write a recursive subroutine which opens a file ? How do : I keep separate filehandles for each recursive call ? Same way. : Is there a simple way to do this or must I generate a unique filehandle name : on each invocation ? That's pretty simple, though it's easy to generate unique filehandles too: $genhandle = 'AAAAAA'; # increments to AAAAAB sub foo { local($FILE) = $genhandle++; # magical autoincrement open($FILE,'foo'); ... &foo(); ... close $FILE; } But I THINK the other way is more efficient, if you reference the filehandle much, since it has to do a symbol table lookup every time you say $FILE, but references to FILE already point to the symbol table entry upon compilation. But it probably takes a little longer to local(*FILE) than local($FILE). It's 6 1/2 of one, and uh, uh, half a baker's dozen of the other. Larry
lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/09/90)
In article <738@alias.UUCP> Reid Ellis <rae%alias@csri.toronto.edu> writes:
: Don't forget that you can use variables for filehandles. I ran into
: the recusion problem myself and found that you couldn't have "local"
: filehandles, so the way I got around this was as follows:
:
: $input = "recursion00";
:
: sub recur
: {
: $input++;
: open($input, "filename");
: if(condition) { &recur(); }
: close($input);
: $input--;
: }
:
: Or something along those lines.. This will give you filehandles with
: names like recursion01, recursion02, recursion03 etc. Note that I
: wrote the above off the top of my head, but you get the idea.
That's the idea, but $input-- isn't magical, so it'll wipe out the value
of $input, turning it into a -1. The when you return from the recursion
you'll try to close filehandle '-1'.
Larry
pem@frankland-river.aaii.oz.au (Paul E. Maisano) (02/09/90)
In article <7020@jpl-devvax.JPL.NASA.GOV>, lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes: > > I believe you can do a local on a name using the type globbing syntax: > > sub foo { > local(*FILE); > > open(FILE,'foo'); > etc. > > I haven't exercised it heavily, but the code is supposedly there to create > a new name if you aren't assigning another name to *FILE. Just as normal > variables created with a null value when you don't assign something to them. This pretty much what I was looking for. It's neater than generating unique filehandle names by hand, but I can't seem to get it to work in a test program. I end up getting a segmentation fault. #!/usr/bin/perl # This is just an otherwise useless program to test recursive opens. sub read_lines { local($name, $n) = @_; local($i); local(*F); open(F, $name) || die "$name: $!\n"; for ($i = 0; $i < $n; $i++) { $_ = <F>; print("$i ($n): ", $_) || warn("print failed: $!\n"); if ($i == 2 && $n <= 10) { &read_lines($name, $n+5); } } close(F); print "finished $n\n"; } &read_lines("/etc/passwd", 5); exit 0; Generating unique names for filehandles does work, though (as I expected). ------------------ Paul E. Maisano Australian Artificial Intelligence Institute 1 Grattan St. Carlton, Vic. 3053, Australia Ph: +613 663-7922 Fax: +613 663-7937 Email: pem@aaii.oz.au
lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/14/90)
In article <1041@frankland-river.aaii.oz.au> pem@frankland-river.aaii.oz.au (Paul E. Maisano) writes: : In article <7020@jpl-devvax.JPL.NASA.GOV>, lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes: : > : > I believe you can do a local on a name using the type globbing syntax: : > : > sub foo { : > local(*FILE); : > : > open(FILE,'foo'); : > etc. : > : > I haven't exercised it heavily, but the code is supposedly there to create : > a new name if you aren't assigning another name to *FILE. Just as normal : > variables created with a null value when you don't assign something to them. : : This pretty much what I was looking for. It's neater than generating unique : filehandle names by hand, but I can't seem to get it to work in a test program. : I end up getting a segmentation fault. I think this will work after the infamous patch #9. Larry