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

📄 ch07_13.htm

📁 By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998
💻 HTM
字号:
<HTML><HEAD><TITLE>Recipe 7.12. Flushing Output (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:02Z"><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_12.htm"TITLE="7.11. Locking a File"><LINKREL="next"HREF="ch07_14.htm"TITLE="7.13. Reading from Many Filehandles Without Blocking"></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_12.htm"TITLE="7.11. Locking a File"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 7.11. Locking a File"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_14.htm"TITLE="7.13. Reading from Many Filehandles Without Blocking"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 7.13. Reading from Many Filehandles Without Blocking"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch07-13576">7.12. Flushing Output</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch07-pgfId-1180">Problem<ACLASS="indexterm"NAME="ch07-idx-1000009697-0"></A><ACLASS="indexterm"NAME="ch07-idx-1000009697-1"></A><ACLASS="indexterm"NAME="ch07-idx-1000009697-2"></A><ACLASS="indexterm"NAME="ch07-idx-1000009697-3"></A><ACLASS="indexterm"NAME="ch07-idx-1000009697-4"></A></A></H3><PCLASS="para">When printing to a filehandle, output doesn't appear immediately. This is a problem in CGI scripts running on some programmer-hostile web servers where, if the web server sees warnings from Perl before it sees the (buffered) output of your script, it sends the browser an uninformative <CODECLASS="literal">500</CODE> <CODECLASS="literal">Server</CODE> <CODECLASS="literal">Error</CODE>. These buffering problems arise with concurrent access to files by multiple programs and when talking with devices or sockets.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch07-pgfId-1186">Solution</A></H3><PCLASS="para">Disable buffering by setting the per-filehandle variable <CODECLASS="literal">$|</CODE> to a true value, customarily <CODECLASS="literal">1</CODE>:</P><PRECLASS="programlisting">$old_fh = select(OUTPUT_HANDLE);$| = 1;select($old_fh);</PRE><PCLASS="para">Or, if you don't mind the expense, disable it by calling the <CODECLASS="literal">autoflush</CODE> method from the IO modules:</P><PRECLASS="programlisting">use IO::Handle;OUTPUT_HANDLE-&gt;autoflush(1);</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch07-pgfId-1204">Discussion</A></H3><PCLASS="para">In most stdio implementations, buffering varies with the type of output device. Disk files are block buffered, often with a buffer size of more than 2K. Pipes and sockets are often buffered with a buffer size between <SUPCLASS="superscript">1</SUP>/<SUBCLASS="subscript">2</SUB> and 2K. Serial devices, including terminals, modems, mice, and joysticks, are normally line-buffered; stdio sends the entire line out only when it gets the newline.</P><PCLASS="para">Perl's <CODECLASS="literal">print</CODE> function does not support truly unbuffered output &nbsp;-  a physical write for each individual character. Instead, it supports <EMCLASS="emphasis">command buffering</EM>, in which one physical write is made after every separate output command. This isn't as hard on your system as no buffering at all, and it still gets the output where you want it, when you want it.</P><PCLASS="para"><ACLASS="indexterm"NAME="ch07-idx-1000009711-0"></A><ACLASS="indexterm"NAME="ch07-idx-1000009711-1"></A><ACLASS="indexterm"NAME="ch07-idx-1000009711-2"></A>Control output buffering through the <CODECLASS="literal">$|</CODE><ACLASS="indexterm"NAME="ch07-idx-1000009715-0"></A> special variable. Enable command buffering by setting it to a true value. It has no effect upon input; see Recipes <ACLASS="xref"HREF="ch15_07.htm"TITLE="Reading from the Keyboard">Recipe 15.6</A> and <ACLASS="xref"HREF="ch15_09.htm"TITLE="Using POSIX termios">Recipe 15.8</A> for unbuffered input. Set this variable to a false value to use default stdio buffering. <ACLASS="xref"HREF="ch07_13.htm#ch07-30274"TITLE="seeme">Example 7.6</A> illustrates the difference.</P><DIVCLASS="example"><H4CLASS="example"><ACLASS="title"NAME="ch07-30274">Example 7.6: seeme</A></H4><PRECLASS="programlisting">#!/usr/bin/perl -w# <ACLASS="indexterm"NAME="ch07-idx-1000009836-0"></A>seeme - demo stdio output buffering$| = (@ARGV &gt; 0);      # command buffered if arguments givenprint &quot;Now you don't see it...&quot;;sleep 2;print &quot;now you do\n&quot;;</PRE></DIV><PCLASS="para">If you call this program with no arguments, STDOUT is not command buffered. Your terminal (console, window, telnet session, whatever) doesn't receive output until the entire line is completed, so you see nothing for two seconds and then get the full line <CODECLASS="literal">&quot;Now</CODE> <CODECLASS="literal">you</CODE> <CODECLASS="literal">don't</CODE> <CODECLASS="literal">see</CODE> <CODECLASS="literal">it</CODE> <CODECLASS="literal">...</CODE> <CODECLASS="literal">now</CODE> <CODECLASS="literal">you</CODE> <CODECLASS="literal">do&quot;</CODE>. If you call the program with at least one argument, STDOUT is command buffered. That means you first see <CODECLASS="literal">&quot;Now</CODE> <CODECLASS="literal">you</CODE> <CODECLASS="literal">don't</CODE> <CODECLASS="literal">see</CODE> <CODECLASS="literal">it...&quot;</CODE>, and then after two seconds you finally see <CODECLASS="literal">&quot;now</CODE> <CODECLASS="literal">you</CODE> <CODECLASS="literal">do&quot;</CODE>.</P><PCLASS="para">The dubious quest for increasingly compact code has led programmers to use the return value of <CODECLASS="literal">select</CODE>, the filehandle that <EMCLASS="emphasis">was</EM> currently selected, as part of the second <CODECLASS="literal">select</CODE>:</P><PRECLASS="programlisting">    select((select(OUTPUT_HANDLE), $| = 1)[0]);</PRE><PCLASS="para">There's another way. The FileHandle and IO modules provide a class method called <CODECLASS="literal">autoflush</CODE>. Call it with true or false values (the default value is true) to control autoflushing on a particular output handle:</P><PRECLASS="programlisting">use FileHandle;STDERR-&gt;autoflush;          # already unbuffered in stdio$filehandle-&gt;autoflush(0);</PRE><PCLASS="para">If you're willing to accept the oddities of indirect object notation covered in <ACLASS="xref"HREF="ch13_01.htm"TITLE="Classes, Objects, and Ties">Chapter 13, <CITECLASS="chapter">Classes, Objects, and Ties</CITE></A>, you can even write something reasonably close to English:</P><PRECLASS="programlisting">use IO::Handle;# assume REMOTE_CONN is an interactive socket handle,# but DISK_FILE is a handle to a regular file.autoflush REMOTE_CONN  1;           # unbuffer for clarityautoflush DISK_FILE    0;           # buffer this for speed</PRE><PCLASS="para">This avoids the bizarre <CODECLASS="literal">select</CODE> business, and makes your code much more readable. Unfortunately, your program takes longer to compile because you're now including the IO::Handle module, so thousands and thousands of lines must first be read and compiled. Learn to manipulate <CODECLASS="literal">$|</CODE> directly, and you'll be happy.</P><PCLASS="para">To ensure that your output gets where you want it, when you want it, buffer flushing is important. It's particularly important with sockets, pipes, and devices, because you may be trying to do interactive I/O with these&nbsp;- more so, in fact, because you can't assume line-buffering. Consider the program in <ACLASS="xref"HREF="ch07_13.htm#ch07-18422"TITLE="getpcomidx">Example 7.7</A>.</P><DIVCLASS="example"><H4CLASS="example"><ACLASS="title"NAME="ch07-18422">Example 7.7: getpcomidx</A></H4><PRECLASS="programlisting">#!/usr/bin/perl# <ACLASS="indexterm"NAME="ch07-idx-1000009840-0"></A>getpcomidx - fetch www.perl.com's index.html documentuse IO::Socket;$sock = new IO::Socket::INET (PeerAddr =&gt; 'www.perl.com',                              PeerPort =&gt; 'http(80)');die &quot;Couldn't create socket: $@&quot; unless $sock;# the library doesn't support $! setting; it uses $@$sock-&gt;autoflush(1);# Mac *must* have \015\012\015\012 instead of \n\n here.# It's a good idea for others, too, as that's the spec,# but implementations are encouraged to accept &quot;\cJ\cJ&quot; too,# and as far as we've seen, they do.$sock-&gt;print(&quot;GET /index.html http/1.1\n\n&quot;);$document = join('', $sock-&gt;getlines());print &quot;DOC IS: $document\n&quot;;</PRE></DIV><PCLASS="para">There's no way to control input buffering using any kind of flushing discussed so far. For that, you need to see Recipes <ACLASS="xref"HREF="ch15_07.htm"TITLE="Reading from the Keyboard">Recipe 15.6</A> and <ACLASS="xref"HREF="ch15_09.htm"TITLE="Using POSIX termios">Recipe 15.8</A>.<ACLASS="indexterm"NAME="ch07-idx-1000009699-0"></A><ACLASS="indexterm"NAME="ch07-idx-1000009699-1"></A><ACLASS="indexterm"NAME="ch07-idx-1000009699-2"></A><ACLASS="indexterm"NAME="ch07-idx-1000009699-3"></A><ACLASS="indexterm"NAME="ch07-idx-1000009699-4"></A></P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch07-pgfId-1000011126">See Also</A></H3><PCLASS="para">The <CODECLASS="literal">$|</CODE> entry in <ICLASS="filename">perlvar  </I>(1), and in the <ACLASS="olink"HREF="../prog/ch02_09.htm#">"Special Variables"</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>; the documentation for the standard FileHandle and IO::Handle modules (also in <ACLASS="olink"HREF="../prog/ch07_01.htm">Chapter 7</A> of <CITECLASS="citetitle">Programming Perl </CITE>); the <CODECLASS="literal">select</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></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_12.htm"TITLE="7.11. Locking a File"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 7.11. Locking a File"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_14.htm"TITLE="7.13. Reading from Many Filehandles Without Blocking"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 7.13. Reading from Many Filehandles Without Blocking"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">7.11. Locking a File</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.13. Reading from Many Filehandles Without Blocking</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 + -