Maison  >  Article  >  php教程  >  PHP中feof()函数的猜测

PHP中feof()函数的猜测

WBOY
WBOYoriginal
2016-06-13 11:31:461523parcourir

<span 本文环境:
OS:Mac OS X </span>10.8.4<span 
PHP:</span>5.3.15

  PHP的官方手册中,函数feof()下面的讨论不少,对此做了一些相关的测试。

<span  1</span> <?<span php
</span><span  2</span> <span print</span> <<<<span EOF
</span><span  3</span> <!DOCTYPE html>
<span  4</span> <html>
<span  5</span>     <head>
<span  6</span>         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<span  7</span>         <title>测试PHP中的feof()函数效果</title>
<span  8</span>     </head>
<span  9</span>     <body>
<span 10</span>         <div>
<span 11</span> <span EOF;
</span><span 12</span> 
<span 13</span> <span function</span> bool2str(<span $bool</span><span ) {
</span><span 14</span>     <span if</span> (<span $bool</span> == <span TRUE</span><span ) {
</span><span 15</span>         <span return</span> "TRUE"<span ;
</span><span 16</span>     } <span else</span><span  {
</span><span 17</span>         <span return</span> "FALSE"<span ;
</span><span 18</span> <span     }
</span><span 19</span> <span }
</span><span 20</span> 
<span 21</span> <span /*</span>
<span 22</span> <span  * 请随便创建一个文件。
</span><span 23</span> <span  * 比如:本测试中,在脚本文件的相同路径下创建了一个文本文件,
</span><span 24</span> <span  * 文件内容为&ldquo;abcdefg&rdquo;,文件名为&ldquo;7bytesfile&rdquo;。
</span><span 25</span>  <span */</span>
<span 26</span> <span $filename</span> = './7bytesfile'<span ;
</span><span 27</span> <span $handle</span> = <span fopen</span>(<span $filename</span>, 'r'<span );
</span><span 28</span> <span if</span> (!<span $handle</span><span ) {
</span><span 29</span>     <span die</span>("文件打开失败"<span );
</span><span 30</span> <span }
</span><span 31</span> 
<span 32</span> <span for</span>(<span $i</span> = 0; <span $i</span> <= <span filesize</span>(<span $filename</span>); <span $i</span>++<span ) {
</span><span 33</span>     <span fseek</span>(<span $handle</span>, <span $i</span><span );
</span><span 34</span>     <span echo</span> "文件位置" . <span ftell</span>(<span $handle</span>) . ":<br />\n"<span ;
</span><span 35</span>     <span echo</span> "执行fseek,尚未执行读取操作之前,feof结果:" . bool2str(<span feof</span>(<span $handle</span>)) . "<br />\n"<span ;
</span><span 36</span>     <span echo</span> "当前位置字符:" . <span fgetc</span>(<span $handle</span>) . "<br />\n"<span ;
</span><span 37</span>     <span echo</span> "执行文件读取操作之后,feof结果:" . bool2str(<span feof</span>(<span $handle</span>)) . "<hr />\n"<span ;
</span><span 38</span> <span }
</span><span 39</span> <span /*</span>
<span 40</span> <span  * 通过上面一段代码可以观察到,
</span><span 41</span> <span  * 随着循环的执行,文件指针从文件头一直移动到文件末尾。
</span><span 42</span> <span  * 但是当完成了字符&ldquo;g&rdquo;的读取输出,文件指针继续向后移动,这是feof()依然返回False。
</span><span 43</span> <span  * 只有当执行了一次fgetc()操作之后,才返回true,表示到达文件末尾。
</span><span 44</span>  <span */</span>
<span 45</span> 
<span 46</span> <span echo</span> "ftell()结果:". <span ftell</span>(<span $handle</span>). "<hr />\n"<span ;
</span><span 47</span> <span //</span><span 输出一下,很郁闷的发现文件指针的位置还是7。+_+</span>
<span 48</span> 
<span 49</span> <span fseek</span>(<span $handle</span>, 4<span );
</span><span 50</span> <span echo</span> "文件位置" . <span ftell</span>(<span $handle</span>) . ":<br />\n"<span ;
</span><span 51</span> <span echo</span> "执行fseek,尚未执行读取操作之前,feof结果:" . bool2str(<span feof</span>(<span $handle</span>)) . "<br />\n"<span ;
</span><span 52</span> <span echo</span> "当前位置字符:" . <span fgetc</span>(<span $handle</span>) . "<br />\n"<span ;
</span><span 53</span> <span echo</span> "执行文件读取操作之后,feof结果:" . bool2str(<span feof</span>(<span $handle</span>)) . "<hr />\n"<span ;
</span><span 54</span> 
<span 55</span> <span fseek</span>(<span $handle</span>, 7<span );
</span><span 56</span> <span echo</span> "文件位置" . <span ftell</span>(<span $handle</span>) . ":<br />\n"<span ;
</span><span 57</span> <span echo</span> "执行fseek,尚未执行读取操作之前,feof结果:" . bool2str(<span feof</span>(<span $handle</span>)) . "<br />\n"<span ;
</span><span 58</span> <span echo</span> "当前位置字符:" . <span fgetc</span>(<span $handle</span>) . "<br />\n"<span ;
</span><span 59</span> <span echo</span> "执行文件读取操作之后,feof结果:" . bool2str(<span feof</span>(<span $handle</span>)) . "<hr />\n"<span ;
</span><span 60</span> <span fclose</span>(<span $handle</span><span );
</span><span 61</span> <span //</span><span 再次移动文件指针,效果依旧。
</span><span 62</span> <span //再用另外一段代码测试一下:</span>
<span 63</span> 
<span 64</span> <span $handle</span> = <span fopen</span>(<span $filename</span>, 'r'<span );
</span><span 65</span> <span if</span> (!<span $handle</span><span ) {
</span><span 66</span>     <span die</span>("文件打开失败"<span );
</span><span 67</span> <span }
</span><span 68</span> <span while</span> (!<span feof</span>(<span $handle</span><span )) {
</span><span 69</span>     <span $char</span> = <span fgetc</span>(<span $handle</span><span );
</span><span 70</span>     <span if</span> (<span $char</span> === <span FALSE</span><span ) {
</span><span 71</span>         <span echo</span> 'FALSE'<span ;
</span><span 72</span>     } <span else</span><span  {
</span><span 73</span>         <span echo</span> <span $char</span><span ;
</span><span 74</span> <span     }
</span><span 75</span> <span }
</span><span 76</span> <span fclose</span>(<span $handle</span><span );
</span><span 77</span> <span //</span><span 依然是输出了字符g之后,再次执行读取操作,才终止循环。</span>
<span 78</span> 
<span 79</span> <span print</span> <<<<span EOF
</span><span 80</span>         </div>
<span 81</span>     </body>
<span 82</span> </html>
<span 83</span> <span EOF;
</span><span 84</span> ?>

  针对这种情况的猜测是,在PHP中,feof()的实现方式并非直接检查文件指针相对于文件的位置,而是根据某个标识返回结果。每次fseek()之后都会都会把这个标识设置为“False”,只有当执行一次文件内容读取操作之后,才会根据文件读取的结果对标识进行设置。

  根据这种猜测,可以使用两种代码逻辑。

  一个方法是不做feof()检测,直接检测内容读取函数(比如fgetc()、fgets())的执行结果。

<span 1</span> <span while</span> ((<span $content</span> = <span fgets</span>(<span $fileHandle</span><span )) !==FALSE) {
</span><span 2</span>     <span //</span><span 文件内容处理&hellip;&hellip;  </span>
<span 3</span> }

  这种处理办法,利用了PHP被诟病的函数返回方式,所以得用“===”或“!==”进行检测,不能把代码简化成:

<span while</span> (<span $content</span> = <span fgets</span>(<span $fileHandle</span>)) {}

  另外一个方法是先进行一次文件读取,然后再进入feof()循环:

<span 1</span> <span $content</span> = <span fgets</span>(<span $fileHandle</span><span );
</span><span 2</span> <span while</span> (!<span feof</span>(<span $fileHandle</span><span )) {
</span><span 3</span>     <span //</span><span 处理文件内容&hellip;&hellip;</span>
<span 4</span>     <span $content</span> = <span fgets</span>(<span $fileHandle</span><span );  
</span><span 5</span> }

  经过测试,似乎前一种方法效率会高一些。

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn