📄 ch08_06.htm
字号:
<HTML><HEAD><TITLE>Recipe 8.5. Trailing a Growing File (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen & Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly & Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:38:41Z"><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="ch08_01.htm"TITLE="8. File Contents"><LINKREL="prev"HREF="ch08_05.htm"TITLE="8.4. Reading a File Backwards by Line or Paragraph"><LINKREL="next"HREF="ch08_07.htm"TITLE="8.6. Picking a Random Line from a File"></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="ch08_05.htm"TITLE="8.4. Reading a File Backwards by Line or Paragraph"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 8.4. Reading a File Backwards by Line or Paragraph"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch08_01.htm"TITLE="8. File Contents"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch08_07.htm"TITLE="8.6. Picking a Random Line from a File"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 8.6. Picking a Random Line from a File"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch08-chap08_trailing_0">8.5. Trailing a Growing File</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch08-pgfId-500">Problem<ACLASS="indexterm"NAME="ch08-idx-1000004647-0"></A><ACLASS="indexterm"NAME="ch08-idx-1000004647-1"></A></A></H3><PCLASS="para">You want to read from a continually growing file, but the read fails when you reach the (current) end of file.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch08-pgfId-506">Solution</A></H3><PCLASS="para">Read until the end of file. Sleep, clear the EOF flag, and read some more. Repeat until interrupted. To clear the EOF flag, either use <CODECLASS="literal">seek</CODE>:</P><PRECLASS="programlisting">for (;;) { while (<FH>) { .... } sleep $SOMETIME; seek(FH, 0, 1);}</PRE><PCLASS="para">or the IO::Handle module's <CODECLASS="literal">clearerr</CODE> method:</P><PRECLASS="programlisting">use IO::Seekable;for (;;) { while (<FH>) { .... } sleep $SOMETIME; FH->clearerr();}</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch08-pgfId-538">Discussion</A></H3><PCLASS="para">When you read to the end of a file, an internal flag is set that prevents further reading. The most direct way to clear this flag is the <CODECLASS="literal">clearerr</CODE><ACLASS="indexterm"NAME="ch08-idx-1000004653-0"></A> method, if supported: it's in the IO::Handle and FileHandle modules.</P><PRECLASS="programlisting">$naptime = 1;use IO::Handle;open (LOGFILE, "/tmp/logfile") or die "can't open /tmp/logfile: $!";for (;;) { while (<LOGFILE>) { print } # or appropriate processing sleep $naptime; LOGFILE->clearerr(); # clear stdio error flag}</PRE><PCLASS="para">If that simple approach doesn't work on your system, you may need to use <CODECLASS="literal">seek</CODE><ACLASS="indexterm"NAME="ch08-idx-1000004654-0"></A>. The <CODECLASS="literal">seek</CODE> code given above tries to move zero bytes from the current position, which nearly always works. It doesn't change the current position, but it should clear the end-of-file condition on the handle so that the next <CODECLASS="literal"><LOGFILE></CODE> picks up new data.</P><PCLASS="para">If that still doesn't work (e.g., it relies on features of your C library's (so-called) standard I/O implementation), then you may need to use the following <CODECLASS="literal">seek</CODE> code, which remembers the old file position explicitly and returns there directly.</P><PRECLASS="programlisting">for (;;) { for ($curpos = tell(LOGFILE); <LOGFILE>; $curpos = tell(LOGFILE)) { # process $_ here } sleep $naptime; seek(LOGFILE, $curpos, 0); # seek to where we had been}</PRE><PCLASS="para">On some kinds of filesystems, the file could be removed while you are reading it. If so, there's probably little reason to continue checking whether it grows. To make the program exit in that case, <CODECLASS="literal">stat</CODE> the handle and make sure its link count (the third field in the return list) hasn't gone to 0:</P><PRECLASS="programlisting">exit if (stat(LOGFILE))[3] == 0</PRE><PCLASS="para">If you're using the <ACLASS="indexterm"NAME="ch08-idx-1000004655-0"></A>File::stat module, you could write that more readably as:</P><PRECLASS="programlisting">use File::stat;exit if stat(*LOGFILE)->nlink == 0;<ACLASS="indexterm"NAME="ch08-idx-1000004649-0"></A><ACLASS="indexterm"NAME="ch08-idx-1000004649-1"></A></PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch08-pgfId-590">See Also</A></H3><PCLASS="para">The <CODECLASS="literal">seek</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>; your system's <ICLASS="filename">tail </I>(1) and <ICLASS="filename">stdio</I> (3) manpages</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="ch08_05.htm"TITLE="8.4. Reading a File Backwards by Line or Paragraph"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 8.4. Reading a File Backwards by Line or Paragraph"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="ch08_07.htm"TITLE="8.6. Picking a Random Line from a File"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 8.6. Picking a Random Line from a File"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">8.4. Reading a File Backwards by Line or Paragraph</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">8.6. Picking a Random Line from a File</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 © 2002</a> O'Reilly & 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 + -