<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML ><HEAD ><TITLE >stream_register_wrapper</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK REL="HOME" TITLE="PHP 手册" HREF="index.html"><LINK REL="UP" TITLE="Stream Functions" HREF="ref.stream.html"><LINK REL="PREVIOUS" TITLE="stream_socket_shutdown" HREF="function.stream-socket-shutdown.html"><LINK REL="NEXT" TITLE="stream_wrapper_restore" HREF="function.stream-wrapper-restore.html"><META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8"></HEAD ><BODY CLASS="refentry" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" >PHP 手册</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="function.stream-socket-shutdown.html" ACCESSKEY="P" >上一页</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" ></TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="function.stream-wrapper-restore.html" ACCESSKEY="N" >下一页</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><H1 ><A NAME="function.stream-wrapper-register" ></A >stream_register_wrapper</H1 ><DIV CLASS="refnamediv" ><A NAME="AEN224179" ></A ><P > (PHP 4 >= 4.3.0, PHP 5)</P >stream_register_wrapper -- 注册一个用 PHP 类实现的 URL 封装协议</DIV ><DIV CLASS="refsect1" ><A NAME="AEN224182" ></A ><H2 >说明</H2 >boolean <B CLASS="methodname" >stream_register_wrapper</B > ( string protocol, string classname )<BR ></BR ><P > <B CLASS="function" >stream_register_wrapper()</B > 允许用户实现自定义的协议处理器和流,用于所有其它的文件系统函数中(例如 <A HREF="function.fopen.html" ><B CLASS="function" >fopen()</B ></A >,<A HREF="function.fread.html" ><B CLASS="function" >fread()</B ></A > 等)。 </P ><P > 要实现一个封装协议,需要按照如下定义声明一个包含有一些函数的类。当有人对你的流使用 fopen 时,PHP 将创建一个 <CODE CLASS="parameter" >classname</CODE > 的实例并调用该实例的方法。必须严格按照如下的描述实现方法 - 否则将导致不明确的行为。 </P ><P > 如果 <CODE CLASS="parameter" >protocol</CODE > 已经有了处理协议,则 <B CLASS="function" >stream_register_wrapper()</B > 将返回 <TT CLASS="constant" ><B >FALSE</B ></TT >。 </P >boolean <B CLASS="methodname" >stream_open</B > ( string path, string mode, int options, string opened_path )<BR ></BR ><P > 当你的流对象被创建之后立即会调用此方法。<CODE CLASS="parameter" >path</CODE > 指定了传入 <A HREF="function.fopen.html" ><B CLASS="function" >fopen()</B ></A > 以及此对象需要取回的 URL。可以用 <A HREF="function.parse-url.html" ><B CLASS="function" >parse_url()</B ></A > 来将此 URL 分割成几部分。 </P ><P > <CODE CLASS="parameter" >mode</CODE > 用来打开文件的模式,和 <A HREF="function.fopen.html" ><B CLASS="function" >fopen()</B ></A > 中的一样。你有责任检查 <CODE CLASS="parameter" >mode</CODE > 对于所请求的 <CODE CLASS="parameter" >path</CODE > 是否合法。 </P ><P > <CODE CLASS="parameter" >options</CODE > 保存了通过流 API 设定的附加标志。可以保存以下一个值或者用 OR 合并的多个值。 <DIV CLASS="informaltable" ><P ></P ><A NAME="AEN224229" ></A ><TABLE BORDER="1" CLASS="CALSTABLE" ><COL><COL><THEAD ><TR ><TH >标志</TH ><TH >说明</TH ></TR ></THEAD ><TBODY ><TR ><TD >STREAM_USE_PATH</TD ><TD >如果 <CODE CLASS="parameter" >path</CODE > 是相对路径,则用 include_path 搜索资源。 </TD ></TR ><TR ><TD >STREAM_REPORT_ERRORS</TD ><TD >如果设定了本标志,你有责任在打开流时用 <A HREF="function.trigger-error.html" ><B CLASS="function" >trigger_error()</B ></A > 来唤起错误。如果没有设定这个标志,那么你不需要唤起任何错误。 </TD ></TR ></TBODY ></TABLE ><P ></P ></DIV > </P ><P > 如果成功打开了 <CODE CLASS="parameter" >path</CODE >,并且在 <CODE CLASS="parameter" >options</CODE > 中设定了 STREAM_USE_PATH,你需要将 <CODE CLASS="parameter" >opened_path</CODE > 设定为实际被打开的文件/资源的完整路径。 </P ><P > 如果成功打开了所请求的资源,应该返回 <TT CLASS="constant" ><B >TRUE</B ></TT >,否则返回 <TT CLASS="constant" ><B >FALSE</B ></TT >。 </P >void <B CLASS="methodname" >stream_close</B > ( void )<BR ></BR ><P > 本方法在流关闭时被调用,使用 <A HREF="function.fclose.html" ><B CLASS="function" >fclose()</B ></A >。必须释放被流锁定或分配的任何资源。 </P >string <B CLASS="methodname" >stream_read</B > ( int count )<BR ></BR ><P > 当对流进行 <A HREF="function.fread.html" ><B CLASS="function" >fread()</B ></A > 和 <A HREF="function.fgets.html" ><B CLASS="function" >fgets()</B ></A > 操作时本方法被调用。必须从当前读写位置以字符串返回最多 <CODE CLASS="parameter" >count</CODE > 字节的数据。如果可用数据少于 <CODE CLASS="parameter" >count</CODE > 字节,则返回尽可能多的数据。如果没有可供返回的数据,返回 <TT CLASS="constant" ><B >FALSE</B ></TT > 或者空字符串。必须用成功读取的字节数去更新流的读写位置。 </P >int <B CLASS="methodname" >stream_write</B > ( string data )<BR ></BR ><P > 当对流进行 <A HREF="function.fwrite.html" ><B CLASS="function" >fwrite()</B ></A > 操作时本方法被调用。必须将 <CODE CLASS="parameter" >data</CODE > 储存到你的流使用的底层存储空间去。如果没有足够的空间了,则试着保存尽可能多的字节。应该返回成功被保存入流的字节数,或者没有保存时返回 0。必须用成功写入的字节数去更新流的读写位置。 </P >boolean <B CLASS="methodname" >stream_eof</B > ( void )<BR ></BR ><P > 当对流进行 <A HREF="function.feof.html" ><B CLASS="function" >feof()</B ></A > 操作时本方法被调用。如果读写位置到了流的尽头或者没有更多数据可读时返回 <TT CLASS="constant" ><B >TRUE</B ></TT >,否则返回 <TT CLASS="constant" ><B >FALSE</B ></TT >。 </P >int <B CLASS="methodname" >stream_tell</B > ( void )<BR ></BR ><P > 当对流进行 <A HREF="function.ftell.html" ><B CLASS="function" >ftell()</B ></A > 操作时本方法被调用。应该返回流的当前读写位置。 </P >boolean <B CLASS="methodname" >stream_seek</B > ( int offset, int whence )<BR ></BR ><P > 当对流进行 <A HREF="function.fseek.html" ><B CLASS="function" >fseek()</B ></A > 操作时本方法被调用。应该根据 <CODE CLASS="parameter" >offset</CODE > 和 <CODE CLASS="parameter" >whence</CODE > 来更新流的读写位置。这些参数的更多信息见 <A HREF="function.fseek.html" ><B CLASS="function" >fseek()</B ></A >。如果位置成功更新了则返回 <TT CLASS="constant" ><B >TRUE</B ></TT >,否则返回 <TT CLASS="constant" ><B >FALSE</B ></TT >。 </P >boolean <B CLASS="methodname" >stream_flush</B > ( void )<BR ></BR ><P > 当对流进行 <A HREF="function.fflush.html" ><B CLASS="function" >fflush()</B ></A > 操作时本方法被调用。如果你在流中缓存了数据还没有写入底层存储空间时,那现在应该做了。如果缓存数据被成功保存(或没有数据可供保存)时返回 <TT CLASS="constant" ><B >TRUE</B ></TT >,当数据无法被保存时返回 <TT CLASS="constant" ><B >FALSE</B ></TT >。 </P ><P > 下面的例子实现了一个 var:// 协议处理器,可以允许使用标准的文件系统流函数来对指定的全局变量进行读写操作,例如 <A HREF="function.fread.html" ><B CLASS="function" >fread()</B ></A >。var:// 协议的实现如下,给出 url "var://foo" 将可以读写 $GLOBALS["foo"]。 <TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" CLASS="EXAMPLE" ><TR ><TD ><DIV CLASS="example" ><A NAME="AEN224326" ></A ><P ><B >例 1. 读写全局变量的流</B ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> class VariableStream {<br /> var $position;<br /> var $varname;<br /> <br /> function stream_open($path, $mode, $options, &$opened_path)<br /> {<br /> $url = parse_url($path);<br /> $this->varname = $url["host"];<br /> $this->position = 0;<br /> <br /> return true;<br /> }<br /><br /> function stream_read($count)<br /> {<br /> $ret = substr($GLOBALS[$this->varname], $this->position, $count);<br /> $this->position += strlen($ret);<br /> return $ret;<br /> }<br /><br /> function stream_write($data)<br /> {<br /> $left = substr($GLOBALS[$this->varname], 0, $this->position);<br /> $right = substr($GLOBALS[$this->varname], $this->position + strlen($data));<br /> $GLOBALS[$this->varname] = $left . $data . $right;<br /> $this->position += strlen($data);<br /> return strlen($data);<br /> }<br /><br /> function stream_tell()<br /> {<br /> return $this->position;<br /> }<br /><br /> function stream_eof()<br /> {<br /> return $this->position >= strlen($GLOBALS[$this->varname]);<br /> }<br /><br /> function stream_seek($offset, $whence)<br /> {<br /> switch($whence) {<br /> case SEEK_SET:<br /> if ($offset < strlen($GLOBALS[$this->varname]) && $offset >= 0) {<br /> $this->position = $offset;<br /> return true;<br /> } else {<br /> return false;<br /> }<br /> break;<br /> <br /> case SEEK_CUR:<br /> if ($offset >= 0) {<br /> $this->position += $offset;<br /> return true;<br /> } else {<br /> return false;<br /> }<br /> break;<br /> <br /> case SEEK_END:<br /> if (strlen($GLOBALS[$this->varname]) + $offset >= 0) {<br /> $this->position = strlen($GLOBALS[$this->varname]) + $offset;<br /> return true;<br /> } else {<br /> return false;<br /> }<br /> break;<br /> <br /> default:<br /> return false;<br /> }<br /> }<br />}<br /><br />stream_register_wrapper("var", "VariableStream")<br /> or die("Failed to register protocol");<br /><br />$myvar = "";<br /> <br />$fp = fopen("var://myvar", "r+");<br /><br />fwrite($fp, "line1\n");<br />fwrite($fp, "line2\n");<br />fwrite($fp, "line3\n");<br /><br />rewind($fp);<br />while(!feof($fp)) {<br /> echo fgets($fp)<br />}<br />fclose($fp);<br />var_dump($myvar);</font> </code></TD ></TR ></TABLE ></DIV ></TD ></TR ></TABLE > </P ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="function.stream-socket-shutdown.html" ACCESSKEY="P" >上一页</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >起始页</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="function.stream-wrapper-restore.html" ACCESSKEY="N" >下一页</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >stream_socket_shutdown</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="ref.stream.html" ACCESSKEY="U" >上一级</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >stream_wrapper_restore</TD ></TR ></TABLE ></DIV ></BODY ></HTML >