Stream ist eine der am häufigsten übersehenen Funktionsreihen (SPL-Reihe, Stream-Reihe, Pack-Funktion, Verpackungsprotokoll) in der PHP-Entwicklung, aber es ist eine sehr nützliche und wichtige Funktion. Stream kann als „Stream“ übersetzt werden. In Java ist Stream ein sehr wichtiges Konzept.
Das Konzept des Streams geht auf das Konzept der Pipe in UNIX zurück. Unter UNIX ist eine Pipe ein ununterbrochener Bytestrom, der zur Implementierung der Kommunikation zwischen Programmen oder Prozessen oder zum Lesen und Schreiben von Peripheriegeräten, externen Dateien usw. verwendet wird. Entsprechend der Richtung des Streams kann er in Eingabestream und Ausgabestream unterteilt werden. Gleichzeitig können andere Streams um ihn herum platziert werden, z. B. ein Pufferstream, sodass mehr Stream-Verarbeitungsmethoden erhalten werden können.
Streams in PHP und Streams in Java sind eigentlich das gleiche Konzept, nur etwas einfacher. Da PHP hauptsächlich für die Webentwicklung verwendet wird, wird der Begriff „Flow“ selten erwähnt. Wenn Sie über eine Java-Grundlage verfügen, ist es einfacher, Streams in PHP zu verstehen. Tatsächlich beziehen sich viele erweiterte Funktionen in PHP, wie SPL, Ausnahmen, Filter usw., alle auf die Implementierung von Java und haben die gleichen Konzepte und Prinzipien.
Das Folgende ist beispielsweise eine Verwendung der PHP-SPL-Standardbibliothek (das Verzeichnis durchsuchen und Dateien mit festen Bedingungen finden):
class RecursiveFileFilterIterator extends FilterIterator { // 满足条件的扩展名 protected $ext = array('jpg','gif'); /** * 提供 $path 并生成对应的目录迭代器 */ public function __construct($path) { parent::__construct(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path))); } /** * 检查文件扩展名是否满足条件 */ public function accept() { $item = $this->getInnerIterator(); if ($item->isFile() && in_array(pathinfo($item->getFilename(), PATHINFO_EXTENSION), $this->ext)) { return TRUE; } } } // 实例化 foreach (new RecursiveFileFilterIterator('D:/history') as $item) { echo $item . PHP_EOL; }
Es gibt auch den gleichen Code in Java:
public class DirectoryContents { public static void main(String[] args) throws IOException { File f = new File("."); // current directory FilenameFilter textFilter = new FilenameFilter() { public boolean accept(File dir, String name) { String lowercaseName = name.toLowerCase(); if (lowercaseName.endsWith(".txt")) { return true; } else { return false; } } }; File[] files = f.listFiles(textFilter); for (File file : files) { if (file.isDirectory()) { System.out.print("directory:"); } else { System.out.print(" file:"); } System.out.println(file.getCanonicalPath()); } } }
Um dieses Beispiel zu nennen: Einerseits zeigt es, dass die Konzepte von PHP und Java in vielen Aspekten gleich sind Andererseits hilft dieses Beispiel auch mit dem Filterflussfilter, den wir unten erwähnen werden. Tatsächlich ist es auch eine Manifestation eines Designmusters.
Wir können die Verwendung von Stream-Serienfunktionen zunächst anhand einiger Beispiele verstehen.
Das Folgende ist ein Beispiel für die Verwendung von Socket zum Erfassen von Daten:
$post_ =array ( 'author' => 'Gonn', 'mail'=>'gonn@nowamagic.net', 'url'=>'http://www.nowamagic.net/', 'text'=>'欢迎访问简明现代魔法'); $data=http_build_query($post_); $fp = fsockopen("nowamagic.net", 80, $errno, $errstr, 5); $out="POST http://nowamagic.net/news/1/comment HTTP/1.1\r\n"; $out.="Host: typecho.org\r\n"; $out.="User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13"."\r\n"; $out.="Content-type: application/x-www-form-urlencoded\r\n"; $out.="PHPSESSID=082b0cc33cc7e6df1f87502c456c3eb0\r\n"; $out.="Content-Length: " . strlen($data) . "\r\n"; $out.="Connection: close\r\n\r\n"; $out.=$data."\r\n\r\n"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 1280); } fclose($fp);
Wir können dies auch mit stream_socket erreichen. Es ist sehr einfach, den Code zu ändern, um den Socket zu öffnen Folgendes. :
$fp = stream_socket_client("tcp://nowamagic.net:80", $errno, $errstr, 3);
Sehen wir uns noch einmal ein Stream-Beispiel an:
file_get_contents函数一般常用来读取文件内容,但这个函数也可以用来抓取远程url,起到和curl类似的作用。 $opts = array ( 'http'=>array( 'method' => 'POST', 'header'=> "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($data) . "\r\n", 'content' => $data) ); $context = stream_context_create($opts); file_get_contents('http://nowamagic.net/news/1/comment', false, $context);
Beachten Sie, dass der dritte Parameter, $context, der HTTP-Stream-Kontext ist, der verstanden werden kann als eine Funktion, die für die Root-Pipe file_get_contents festgelegt ist. Auf die gleiche Weise können wir auch FTP-Streams und Socket-Streams erstellen und diese in den entsprechenden Funktionen einstellen.
Weitere Informationen zu stream_context_create finden Sie unter: Vervollständigung der PHP-Funktion: stream_context_create() simuliert POST/GET.
Die beiden oben genannten Stream-Serienfunktionen sind Wrapper-ähnliche Streams, die auf die Eingabe- und Ausgabestreams eines bestimmten Protokolls einwirken. Diese Art der Verwendung und dieses Konzepts unterscheiden sich eigentlich nicht wesentlich von Streams in Java. Java verfügt beispielsweise häufig über diese Schreibmethode:
new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File(fileName))));
Eine Flow-Ebene ist in einer anderen Flow-Ebene verschachtelt, was ähnlich ist zu PHP. Es gibt verschiedene Ansätze, aber den gleichen Effekt.
Sehen wir uns die Funktion des Filterstreams an:
$fp = fopen('c:/test.txt', 'w+'); /* 把rot13过滤器作用在写入流上 */ stream_filter_append($fp, "string.rot13", STREAM_FILTER_WRITE); /* 写入的数据经过rot13过滤器的处理*/ fwrite($fp, "This is a test\n"); rewind($fp); /* 读取写入的数据,独到的自然是被处理过的字符了 */ fpassthru($fp); fclose($fp); // output:Guvf vf n grfg
Wenn wir im obigen Beispiel den Filtertyp auf STREAM_FILTER_ALL festlegen, wirkt er auf die Lese- und Schreibstreams am Gleichzeitig werden die gelesenen und geschriebenen Daten vom rot13-Filter verarbeitet und die von uns gelesenen Daten stimmen mit den ursprünglich geschriebenen Daten überein.
Sie werden vielleicht überrascht sein, dass die Variable „string.rot13“ in stream_filter_append aus dem Nichts kommt. Dies ist tatsächlich ein integrierter Filter in PHP.
Verwenden Sie die folgende Methode, um den in PHP integrierten Stream auszudrucken:
$streamlist = stream_get_filters(); print_r($streamlist);
Ausgabe:
Array ( [0] => convert.iconv.* [1] => mcrypt.* [2] => mdecrypt.* [3] => string.rot13 [4] => string.toupper [5] => string.tolower [6] => string.strip_tags [7] => convert.* [8] => consumed [9] => dechunk [10] => zlib.* [11] => bzip2.* )
Natürlich werden wir darüber nachdenken, unsere eigenen Filter zu definieren , Auch das ist nicht schwer:
class md5_filter extends php_user_filter { function filter($in, $out, &$consumed, $closing) { while ($bucket = stream_bucket_make_writeable($in)) { $bucket->data = md5($bucket->data); $consumed += $bucket->datalen; stream_bucket_append($out, $bucket); } //数据处理成功,可供其它管道读取 return PSFS_PASS_ON; } } stream_filter_register("string.md5", "md5_filter");
Hinweis: Der Filtername ist frei wählbar.
Danach können Sie unseren benutzerdefinierten Filter „string.md5“ verwenden.
Die Art und Weise, wie dieser Filter geschrieben ist, erscheint etwas verwirrend. Tatsächlich müssen wir uns nur die Struktur und die integrierten Methoden der Klasse php_user_filter ansehen, um zu verstehen.
Wofür sich der Filterstream am besten eignet, ist die Konvertierung von Dateiformaten, einschließlich Komprimierung, Kodierung und Dekodierung usw. Zusätzlich zu diesen „abweichenden“ Verwendungen ist einer der nützlicheren Aspekte des Filterstreams das Debuggen und Protokollierungsfunktionen, wie z. B. Es wird gesagt, dass bei der Socket-Entwicklung ein Filterstrom für die Protokollaufzeichnung registriert wird. Zum Beispiel das folgende Beispiel:
class md5_filter extends php_user_filter { public function filter($in, $out, &$consumed, $closing) { $data=""; while ($bucket = stream_bucket_make_writeable($in)) { $bucket->data = md5($bucket->data); $consumed += $bucket->datalen; stream_bucket_append($out, $bucket); } call_user_func($this->params, $data); return PSFS_PASS_ON; } } $callback = function($data) { file_put_contents("c:\log.txt",date("Y-m-d H:i")."\r\n"); };
Dieser Filter kann nicht nur den Eingabestream verarbeiten, sondern auch eine Funktion zur Protokollierung zurückrufen.
kann wie folgt verwendet werden:
stream_filter_prepend($fp, "string.md5", STREAM_FILTER_WRITE,$callback);
Es gibt auch einen sehr wichtigen Stream in den Stream-Serienfunktionen in PHP, nämlich die Wrapper-Klasse stream streamWrapper. Durch die Verwendung von Wrapper-Streams können verschiedene Protokolltypen dieselbe Schnittstelle zum Bearbeiten von Daten verwenden.