⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch07_17.htm

📁 By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998
💻 HTM
字号:
<HTML><HEAD><TITLE>Recipe 7.16. Storing Filehandles in Variables (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen &amp; Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly &amp; Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:37:20Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch07_01.htm"TITLE="7. File Access"><LINKREL="prev"HREF="ch07_16.htm"TITLE="7.15. Determining the Number of Bytes to Read"><LINKREL="next"HREF="ch07_18.htm"TITLE="7.17. Caching Open Output Filehandles"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch07_16.htm"TITLE="7.15. Determining the Number of Bytes to Read"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 7.15. Determining the Number of Bytes to Read"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch07_01.htm"TITLE="7. File Access"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch07_18.htm"TITLE="7.17. Caching Open Output Filehandles"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 7.17. Caching Open Output Filehandles"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch07-25170">7.16. Storing Filehandles in Variables</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch07-pgfId-1592">Problem<ACLASS="indexterm"NAME="ch07-idx-1000009767-0"></A><ACLASS="indexterm"NAME="ch07-idx-1000009767-1"></A><ACLASS="indexterm"NAME="ch07-idx-1000009767-2"></A></A></H3><PCLASS="para">You want to use a <ACLASS="indexterm"NAME="ch07-idx-1000012064-0"></A>filehandle like a normal variable so you can pass it to or return it from a function, store it in a data structure, and so on.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch07-pgfId-1598">Solution</A></H3><PCLASS="para">If you already have a regular symbolic filehandle like STDIN or LOGFILE, use the typeglob notation, <CODECLASS="literal">*FH</CODE>. This is the most efficient approach.</P><PRECLASS="programlisting">$variable = *FILEHANDLE;        # save in variablesubroutine(*FILEHANDLE);        # or pass directlysub subroutine {    my $fh = shift;    print $fh &quot;Hello, filehandle!\n&quot;;}</PRE><PCLASS="para">If you want anonymous filehandles, see the <EMCLASS="emphasis">return_fh</EM> function below, or use the <CODECLASS="literal">new</CODE> method from the IO::File or IO::Handle module, store that in a scalar variable, and use it as though it were a normal filehandle:</P><PRECLASS="programlisting">use FileHandle;                   # make anon filehandle$fh = FileHandle-&gt;new();use IO::File;                     # 5.004 or higher$fh = IO::File-&gt;new();</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch07-pgfId-1630">Discussion</A></H3><PCLASS="para">You have many choices for passing filehandles into a subroutine or storing them in a data structure. The simplest and fastest way is through the <ACLASS="indexterm"NAME="ch07-idx-1000012073-0"></A>typeglob notation, <CODECLASS="literal">*FH</CODE>. It may help you to conceptualize the asterisk as the type symbol for a filehandle. Like the little colored balls from high school chemistry that stood for atomic particles, it's not really true, but it is a convenient mental shorthand. By the time you understand where this model breaks down, you won't need it anymore.</P><PCLASS="para">That works cleanly for simple things, but what if you wanted to make an array of filehandles whose names you didn't know? As shown in <ACLASS="xref"HREF="ch11_01.htm"TITLE="References and Records">Chapter 11, <CITECLASS="chapter">References and Records</CITE></A>, generating anonymous arrays, hashes, and even functions on the fly can prove extremely convenient. It would be nice to be able to do the same with filehandles. That's where the IO modules come in.</P><PCLASS="para">You can generate an anonymous handle with the IO::Handle or IO::File module's <CODECLASS="literal">new</CODE> method. This returns a filehandle you can pass to subroutines, store in arrays, and use however you would use a named filehandle's typeglob &nbsp;-  plus more. You can also use those modules as object classes for inheritance purposes because the return values from the <CODECLASS="literal">new</CODE> constructor are fully fledged objects, complete with available method calls.</P><PCLASS="para">You can use these as <ACLASS="indexterm"NAME="ch07-idx-1000012065-0"></A>indirect filehandles, which saves you the trouble of thinking up filehandle names. Instead, you think up names to store the anonymous filehandles in.</P><PCLASS="para">To capture the typeglob from a named filehandle, prefix it with <CODECLASS="literal">*</CODE>:</P><PRECLASS="programlisting">$fh_a = IO::File-&gt;new(&quot;&lt; /etc/motd&quot;)    or die &quot;open /etc/motd: $!&quot;;$fh_b = *STDIN;some_sub($fh_a, $fh_b);</PRE><PCLASS="para">This isn't the only way, but it is the simplest and most convenient. Its only limitation is that you can't <CODECLASS="literal">bless</CODE> it to turn it into an object. To do this, you must <CODECLASS="literal">bless</CODE> a <EMCLASS="emphasis">reference</EM> to a typeglob &nbsp;-  that's what IO::Handle does. Like typeglobs, references to typeglobs can be safely used as indirect filehandles, whether blessed or not.</P><PCLASS="para">To create and return a new filehandle from a function, do this:</P><PRECLASS="programlisting">sub return_fh {             # make anon filehandle    local *FH;              # must be local, not my    # now open it if you want to, then...    return *FH;}$handle = return_fh();</PRE><PCLASS="para">A subroutine accepting a filehandle argument can either store the argument into a (preferably lexical) variable and use that as an indirect filehandle:</P><PRECLASS="programlisting">sub accept_fh {    my $fh = shift;    print $fh &quot;Sending to indirect filehandle\n&quot;;}</PRE><PCLASS="para">or it can localize a typeglob and use the <ACLASS="indexterm"NAME="ch07-idx-1000012062-0"></A>filehandle directly:</P><PRECLASS="programlisting">sub accept_fh {    local *FH = shift;    print  FH &quot;Sending to localized filehandle\n&quot;;}</PRE><PCLASS="para">Both styles work with either IO::Handle objects or typeglobs of real filehandles:</P><PRECLASS="programlisting">accept_fh(*STDOUT);accept_fh($handle);</PRE><PCLASS="para">Perl accepts many things as indirect <ACLASS="indexterm"NAME="ch07-idx-1000012063-0"></A>filehandles (strings, typeglobs, and references to typeglobs), but unless you pass typeglobs or IO::Handle objects you may run into trouble. Strings (<CODECLASS="literal">&quot;LOGFILE&quot;</CODE> instead of <CODECLASS="literal">*LOGFILE</CODE>) require special finessing to work between packages, and references to typeglobs can't be usefully returned from functions.</P><PCLASS="para">In the preceding examples, we assigned the filehandle to a scalar variable before using it. That is because only simple scalar variables, not expressions or subscripts into hashes or arrays, can be used with built-ins like <CODECLASS="literal">print</CODE>, <CODECLASS="literal">printf</CODE>, or the diamond operator. These are illegal and won't even compile:</P><PRECLASS="programlisting">@fd = (*STDIN, *STDOUT, *STDERR);print $fd[1] &quot;Type it: &quot;;                           # WRONG$got = &lt;$fd[0]&gt;                                     # WRONGprint $fd[2] &quot;What was that: $got&quot;;                 # WRONG</PRE><PCLASS="para">With <CODECLASS="literal">print</CODE> and <CODECLASS="literal">printf</CODE>, you get around this by using a block and an expression where you would place the filehandle:</P><PRECLASS="programlisting">print  { $fd[1] } &quot;funny stuff\n&quot;;printf { $fd[1] } &quot;Pity the poor %x.\n&quot;, 3_735_928_559;<CODECLASS="userinput"><B><CODECLASS="replaceable"><I>Pity the poor deadbeef.</I></CODE></B></CODE></PRE><PCLASS="para">That block is a proper block, so you can put more complicated code there. This sends the message out to one of two places:</P><PRECLASS="programlisting">$ok = -x &quot;/bin/cat&quot;;                print { $ok ? $fd[1] : $fd[2] } &quot;cat stat $ok\n&quot;;print { $fd[ 1 + ($ok || 0) ]  } &quot;cat stat $ok\n&quot;;           </PRE><PCLASS="para">This approach of treating <CODECLASS="literal">print</CODE> and <CODECLASS="literal">printf</CODE> like object methods calls doesn't work for the diamond operator, because it's a real operator, not just a function with a comma-less argument. Assuming you've been storing typeglobs in your structure as we did above, you can use the built-in function named <CODECLASS="literal">readline</CODE> to read a record just as <CODECLASS="literal">&lt;FH&gt;</CODE> does. Given the preceding initialization of <CODECLASS="literal">@fd</CODE>, this would work: <ACLASS="indexterm"NAME="ch07-idx-1000012076-0"></A></P><PRECLASS="programlisting"><ACLASS="indexterm"NAME="ch07-idx-1000012066-0"></A>$got = readline($fd[0]);<ACLASS="indexterm"NAME="ch07-idx-1000009772-0"></A><ACLASS="indexterm"NAME="ch07-idx-1000009772-1"></A><ACLASS="indexterm"NAME="ch07-idx-1000009772-2"></A></PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch07-pgfId-1000009364">See Also</A></H3><PCLASS="para">The <CODECLASS="literal">open</CODE> function in <ICLASS="filename">perlfunc </I>(1) and in <ACLASS="olink"HREF="../prog/ch03_01.htm">Chapter 3</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A>; <ACLASS="xref"HREF="ch07_02.htm"TITLE="Opening a File">Recipe 7.1</A>; the documentation with the standard FileHandle module (also in <ACLASS="olink"HREF="../prog/ch07_01.htm">Chapter 7</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A>); the <ACLASS="olink"HREF="../prog/ch02_03.htm#PERL2-CH-2-SECT-3.6">"Typeglobs and Filehandles"</A> section of <ACLASS="olink"HREF="../prog/ch02_01.htm">Chapter 2</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A> and <ACLASS="olink"HREF="../prog/ch02_01.htm">Chapter 2</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A></P></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch07_16.htm"TITLE="7.15. Determining the Number of Bytes to Read"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 7.15. Determining the Number of Bytes to Read"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch07_18.htm"TITLE="7.17. Caching Open Output Filehandles"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 7.17. Caching Open Output Filehandles"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">7.15. Determining the Number of Bytes to Read</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">7.17. Caching Open Output Filehandles</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font> </p> <map name="library-map"> <area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map> </BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -