using 2-arg open to open to a scalar

X

xhoster

I'm looking for a value to put in $some_string so that the
below code will have $y read from $scalar. I can't use the "<&4" syntax,
since $x doesn't have a real fileno to be duped.


open my $x, "<", \$scalar or die $!;
open my $y, $some_string or die $!;

The context of this is that I have an external (i.e. not my code) module
which won't take a file-handle, it will only take a "filename" which gets
passed to the 2-argument form of open. So I want to craft a magical
"filename" that when given to 2-arg open, does what I want.

Thanks,

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
J

John W. Krahn

I'm looking for a value to put in $some_string so that the
below code will have $y read from $scalar. I can't use the "<&4" syntax,
since $x doesn't have a real fileno to be duped.


open my $x, "<", \$scalar or die $!;
open my $y, $some_string or die $!;

The context of this is that I have an external (i.e. not my code) module
which won't take a file-handle, it will only take a "filename" which gets
passed to the 2-argument form of open. So I want to craft a magical
"filename" that when given to 2-arg open, does what I want.

It will work with a package filehandle:

$ perl -e'
$scalar = <<TEXT;
one two
three four
TEXT

open IN, "<", \$scalar or die $!;
open my $y, "<&=IN" or die $!;
print while <IN>;
print while <$y>;
'
one two
three four
one two
three four



John
 
A

A. Sinan Unur

I'm looking for a value to put in $some_string so that the
below code will have $y read from $scalar. I can't use the "<&4"
syntax, since $x doesn't have a real fileno to be duped.


open my $x, "<", \$scalar or die $!;
open my $y, $some_string or die $!;

The context of this is that I have an external (i.e. not my code)
module which won't take a file-handle, it will only take a "filename"
which gets passed to the 2-argument form of open. So I want to craft
a magical "filename" that when given to 2-arg open, does what I want.

C:\Temp> cat tt.pl
#!/usr/bin/perl
use strict;
use warnings;

use Alias;

my $input_text = <<EOT;
sdksdfk;lf';lk lk l;' k
asfas;l's' k' k'adkd;fka'gka' ' ksf'sg
;sk;sdkg;skg;sk
lsdf;ksdfk
EOT

open my $input, '<', \$input_text;
alias INPUT => $input;

myread( "<&=INPUT");

sub myread {
my ($fn) = @_;

open my $h, $fn or die $!;
print while <$h>;
return;
}

__END__

C:\Temp> tt
sdksdfk;lf';lk lk l;' k
asfas;l's' k' k'adkd;fka'gka' ' ksf'sg
;sk;sdkg;skg;sk
lsdf;ksdfk


--
A. Sinan Unur <[email protected]>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/
 
X

xhoster

A. Sinan Unur said:
C:\Temp> cat tt.pl
#!/usr/bin/perl
use strict;
use warnings;

use Alias;

my $input_text = <<EOT;
sdksdfk;lf';lk lk l;' k
asfas;l's' k' k'adkd;fka'gka' ' ksf'sg
;sk;sdkg;skg;sk
lsdf;ksdfk
EOT

open my $input, '<', \$input_text;
alias INPUT => $input;

myread( "<&=INPUT");

Excellent, thanks. I just had to add the package name because in my
case myread is in a different package.

myread("<&=main::INPUT")

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
A

A. Sinan Unur

....


Excellent, thanks. I just had to add the package name because in my
case myread is in a different package.

myread("<&=main::INPUT")

Glad it worked. This is why I love this group: Prior to your post, I
would never have thought about how to achieve what you want to achieve.
This really helped me learn a lot about the open function some of whose
features I had not paid much attention to before.

Sinan

--
A. Sinan Unur <[email protected]>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/
 
C

C.DeRykus

It will work with a package filehandle:

$ perl -e'
$scalar = <<TEXT;
one two
three four
TEXT

open IN, "<", \$scalar or die $!;
open my $y, "<&=IN" or die $!;
print while <IN>;
print while <$y>;
'
one two

Or, if Alias isn't handy and you want a lexical filehandle instead:

open my $fh, "+<", undef
or die $!;
print $fh $scalar;
seek $fh, 0, 0 or die $!;

open( my $y, "<&=@{[fileno $fh]}" )
or die $!;
 
B

Ben Morrow

Quoth "C.DeRykus said:
open( my $y, "<&=@{[fileno $fh]}" )
or die $!;

Blecch :).

open my $y, "<&=", $fh or die ...;

$fh can be replaced with "STDIN" or \*STDIN if you want to fdopen(3) an
already-existing global filehandle.

Ben
 
X

xhoster

Ben Morrow said:
Quoth "C.DeRykus said:
open( my $y, "<&=@{[fileno $fh]}" )
or die $!;

Blecch :).

open my $y, "<&=", $fh or die ...;

But the requirement was to use the 2-arg form of open, not the
3-arg form.

Well, that was the requirement. Despite the nice answers I've gotten here,
I decided to I'd keep my own library with an updated version of the module
which can take a file-handle in lieu of a string which is passed to 2-arg
open, which obviates the whole mess. Now I just have the mess of multiple
module versions in different places in @INC

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
X

xhoster

Ben Morrow said:
Quoth "C.DeRykus said:
open( my $y, "<&=@{[fileno $fh]}" )
or die $!;

Blecch :).

open my $y, "<&=", $fh or die ...;

But the requirement was to use the 2-arg form of open, not the
3-arg form.

Well, that was the requirement. Despite the nice answers I've gotten
here, I decided to I'd keep my own library with an updated version of the
module which can take a file-handle in lieu of a string which is passed
to 2-arg open, which obviates the whole mess. Now I just have the mess
of multiple module versions in different places in @INC

By the way, what do people consider the "best practice" for detecting
whether the thing passed in is a file-handle, rather than a filename?

if (ref $_[0]) { #...

Seems to be good enough to me. It works with lexicals and with foo(\*FH),
but it fails with foo(*FH). I'm willing to live with that, but if there is
something better which isn't overly complicated it would be better yet.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
B

Ben Morrow

Quoth (e-mail address removed):
By the way, what do people consider the "best practice" for detecting
whether the thing passed in is a file-handle, rather than a filename?

if (ref $_[0]) { #...

Seems to be good enough to me. It works with lexicals and with foo(\*FH),
but it fails with foo(*FH). I'm willing to live with that, but if there is
something better which isn't overly complicated it would be better yet.

use Scalar::Util qw/openhandle/;

if (openhandle $_[0]) {

is what I'd use. It doesn't catch \*FOO where FOO is not an open handle,
nor cases like

open my $x, "<", "foo";
close $x;
if (openhandle $x) {

but that's probably what you wanted anyway.

Ben
 
C

C.DeRykus

Quoth (e-mail address removed):


By the way, what do people consider the "best practice" for detecting
whether the thing passed in is a file-handle, rather than a filename?
if (ref $_[0]) { #...
Seems to be good enough to me. It works with lexicals and with foo(\*FH),
but it fails with foo(*FH). I'm willing to live with that, but if there is
something better which isn't overly complicated it would be better yet.

use Scalar::Util qw/openhandle/;

if (openhandle $_[0]) {

is what I'd use. It doesn't catch \*FOO where FOO is not an open handle,
nor cases like

open my $x, "<", "foo";
close $x;
if (openhandle $x) {

but that's probably what you wanted anyway.

Hm... Scalar::Util 1.18 seems to catch both cases:

perl -lM"Scalar::Util 'openhandle'"
open my $h,"<","/dev/null" or die;
close $h or die;
print openhandle $h ? "yes" : "no";
^D
no


perl -lM"Scalar::Util 'openhandle'"
print openhandle \*FOO ? "yes"
: "no";
^D
no
 
X

xhoster

C.DeRykus said:
Quoth (e-mail address removed):


By the way, what do people consider the "best practice" for detecting
whether the thing passed in is a file-handle, rather than a filename?
if (ref $_[0]) { #...
Seems to be good enough to me. It works with lexicals and with
foo(\*FH), but it fails with foo(*FH). I'm willing to live with
that, but if there is something better which isn't overly complicated
it would be better yet.

use Scalar::Util qw/openhandle/;

if (openhandle $_[0]) {

is what I'd use. It doesn't catch \*FOO where FOO is not an open
handle, nor cases like

open my $x, "<", "foo";
close $x;
if (openhandle $x) {

but that's probably what you wanted anyway.

Hm... Scalar::Util 1.18 seems to catch both cases:

perl -lM"Scalar::Util 'openhandle'"
open my $h,"<","/dev/null" or die;
close $h or die;
print openhandle $h ? "yes" : "no";
^D
no

perl -lM"Scalar::Util 'openhandle'"
print openhandle \*FOO ? "yes"
: "no";
^D
no

Catch in the wrong sense. If the method is being given something
that is either a handle or a filename, and it is supposed to detect
the difference, then one would not want to try to open a stringified handle
as if it were a filename when given something that is a handle but not
an open one. (Especially if it will be for output)

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
C

C.DeRykus

C.DeRykus said:
Quoth (e-mail address removed):
By the way, what do people consider the "best practice" for detecting
whether the thing passed in is a file-handle, rather than a filename?
if (ref $_[0]) { #...
Seems to be good enough to me. It works with lexicals and with
foo(\*FH), but it fails with foo(*FH). I'm willing to live with
that, but if there is something better which isn't overly complicated
it would be better yet.
use Scalar::Util qw/openhandle/;
if (openhandle $_[0]) {
is what I'd use. It doesn't catch \*FOO where FOO is not an open
handle, nor cases like
open my $x, "<", "foo";
close $x;
if (openhandle $x) {
but that's probably what you wanted anyway.
Hm... Scalar::Util 1.18 seems to catch both cases:
perl -lM"Scalar::Util 'openhandle'"
open my $h,"<","/dev/null" or die;
close $h or die;
print openhandle $h ? "yes" : "no";
^D
no
perl -lM"Scalar::Util 'openhandle'"
print openhandle \*FOO ? "yes"
: "no";
^D
no

Catch in the wrong sense. If the method is being given something
that is either a handle or a filename, and it is supposed to detect
the difference, then one would not want to try to open a stringified handle
as if it were a filename when given something that is a handle but not
an open one. (Especially if it will be for output)

Unless I'm missing the boat again
though, wouldn't some combo of
ref, openhandle, and arg inspection
get even closer:

if (ref $_[0]) { #...
Seems to be good enough to me.
It works with lexicals and with
foo(\*FH),
but it fails with foo(*FH).

Maybe something along these lines..

if( not ref $_[0]
and not defined openhandle $_[0]
and substr($_[0],0,1) ne '*' )
# filename...
}
 
B

Ben Morrow

Quoth "C.DeRykus said:
Maybe something along these lines..

if( not ref $_[0]
and not defined openhandle $_[0]
and substr($_[0],0,1) ne '*' )

Better would be

ref \$_[0] ne 'GLOB'

or maybe even

ref \$_[0] eq 'SCALAR'

as otherwise you can't use files whose names begin with '*'...

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,434
Messages
2,571,690
Members
48,796
Latest member
Greg L.

Latest Threads

Top