Heim php教程 php手册 了解PHP中Stream(流)的概念与用法

了解PHP中Stream(流)的概念与用法

Jun 13, 2016 am 09:39 AM
stream 过滤器

Stream是PHP开发里最容易被忽视的函数系列(SPL系列,Stream系列,pack函数,封装协议)之一,但其是个很有用也很重要的函数。Stream可以翻译为“流”,在Java里,流是一个很重要的概念。

流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。根据流的方向又可以分为输入流和输出流,同时可以在其外围再套上其它流,比如缓冲流,这样就可以得到更多流处理方法。

PHP里的流和Java里的流实际上是同一个概念,只是简单了一点。由于PHP主要用于Web开发,所以“流”这块的概念被提到的较少。如果有Java基础,对于PHP里的流就更容易理解了。其实PHP里的许多高级特性,比如SPL,异常,过滤器等都参考了Java的实现,在理念和原理上同出一辙。

比如下面是一段PHP SPL标准库的用法(遍历目录,查找固定条件的文件):

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;
}
Nach dem Login kopieren

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());
        }
    }
}
Nach dem Login kopieren

举这个例子,一方面是说明PHP和Java在很多方面的概念是一样的,掌握一种语言对理解另外一门语言会有很大的帮助;另一方面,这个例子也有助于我们下面要提到的过滤器流-filter。其实也是一种设计模式的体现。

我们可以通过几个例子先来了解stream系列函数的使用。

下面是一个使用socket来抓取数据的例子:

$post_ =array (
	'author' => 'Gonn',
	'mail'=>'gonn@bkjia.com',
	'url'=>'http://www.bkjia.com/',
	'text'=>'欢迎访问帮客之家');

$data=http_build_query($post_);
$fp = fsockopen("bkjia.com", 80, $errno, $errstr, 5);

$out="POST http://bkjia.com/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);
Nach dem Login kopieren

我们也可以用stream_socket 实现,这很简单,只需要打开socket的代码换成下面的即可:

$fp = stream_socket_client("tcp://bkjia.com:80", $errno, $errstr, 3);
Nach dem Login kopieren

再来看一个stream的例子:

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://bkjia.com/news/1/comment', false, $context);
Nach dem Login kopieren

注意第三个参数,$context,即HTTP流上下文,可以理解为套在file_get_contents函数上的一根管道。同理,我们还可以创建FTP流,socket流,并把其套在对应的函数在。

更多关于 stream_context_create,可以参考:PHP函数补完:stream_context_create()模拟POST/GET。

上面提到的两个stream系列的函数都是类似包装器的流,作用在某种协议的输入输出流上。这样的使用方式和概念,其实和Java中的流并没有大的区别,比如Java中经常有这样的写法:

new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File(fileName))));
Nach dem Login kopieren

一层流嵌套着另外一层流,和PHP里有异曲同工之妙。

我们再来看个过滤器流的作用:

$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
Nach dem Login kopieren

在上面的例子中,如果我们把过滤器的类型设置为STREAM_FILTER_ALL,即同时作用在读写流上,那么读写的数据都将被rot13过滤器处理,我们读出的数据就和写入的原始数据是一致的。

你可能会奇怪stream_filter_append中的 "string.rot13"这个变量来的莫名其妙,这实际上是PHP内置的一个过滤器。

使用下面的方法即可打印出PHP内置的流:

$streamlist = stream_get_filters();
print_r($streamlist);
Nach dem Login kopieren

输出:

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.*
)
Nach dem Login kopieren

自然而然,我们会想到定义自己的过滤器,这个也不难:

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");
Nach dem Login kopieren

注意:过滤器名可以随意取。

之后就可以使用"string.md5"这个我们自定义的过滤器了。

这个过滤器的写法看起来很是有点摸不着头脑,事实上我们只需要看一下php_user_filter这个类的结构和内置方法即了解了。

过滤器流最适合做的就是文件格式转换了,包括压缩,编解码等,除了这些“偏门”的用法外,filter流更有用的一个地方在于调试和日志功能,比如说在socket开发中,注册一个过滤器流进行log记录。比如下面的例子:

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");
};
Nach dem Login kopieren

这个过滤器不仅可以对输入流进行处理,还能回调一个函数来进行日志记录。

可以这么使用:

stream_filter_prepend($fp, "string.md5", STREAM_FILTER_WRITE,$callback);
Nach dem Login kopieren

PHP中的stream流系列函数中还有一个很重要的流,就是包装类流 streamWrapper。使用包装流可以使得不同类型的协议使用相同的接口操纵数据。这个以后再说。

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

So debuggen Sie Java Stream-Vorgänge in IntelliJ IDEA So debuggen Sie Java Stream-Vorgänge in IntelliJ IDEA May 09, 2023 am 11:25 AM

Der Stream-Betrieb ist ein Highlight von Java8! Obwohl java.util.stream sehr leistungsfähig ist, gibt es immer noch viele Entwickler, die es selten in der tatsächlichen Arbeit verwenden. Einer der am häufigsten beklagten Gründe ist, dass es zu Beginn schwierig zu debuggen ist, da Streaming-Vorgänge wie z als Stream kann in DEBUG nicht verwendet werden. Wenn es sich um eine Codezeile handelt, werden im nächsten Schritt tatsächlich viele Vorgänge gleichzeitig übergeben, sodass wir schwer beurteilen können, welche Zeile darin das Problem darstellt. Plug-in: JavaStreamDebugger Wenn die von Ihnen verwendete IDEA-Version relativ neu ist, ist dieses Plug-in bereits enthalten und muss nicht installiert werden. Wenn es noch nicht installiert ist, installieren Sie es manuell und fahren Sie dann unten fort.

So erhalten Sie den maximalen Wert aus dem Stream in Java8 So erhalten Sie den maximalen Wert aus dem Stream in Java8 May 14, 2023 pm 03:43 PM

Der Stream von Java8 benötigt maxpublicstaticvoidmain(String[]args){Listlist=Arrays.asList(1,2,3,4,5,6);Integermax=list.stream().max((a,b)->{if ( a>b){return1;}elsereturn-1;}).get();System.out.println(max);}Hinweis: Die Größe wird hier durch positive und negative Zahlen und 0-Werte bestimmt. Anstatt es direkt zu schreiben if(a>b){returna;}elseretur

Vue-Fehler: Der Filter in Filtern kann nicht richtig verwendet werden, wie kann man ihn lösen? Vue-Fehler: Der Filter in Filtern kann nicht richtig verwendet werden, wie kann man ihn lösen? Aug 26, 2023 pm 01:10 PM

Vue-Fehler: Der Filter in Filtern kann nicht richtig verwendet werden, wie kann man ihn lösen? Einführung: In Vue sind Filter eine häufig verwendete Funktion, mit der Daten formatiert oder gefiltert werden können. Allerdings kann es bei der Verwendung manchmal zu Problemen kommen, da wir den Filter nicht richtig verwenden können. In diesem Artikel werden einige häufige Ursachen und Lösungen behandelt. 1. Ursachenanalyse: Der Filter ist nicht korrekt registriert: Filter in Vue müssen registriert werden, bevor sie in Vorlagen verwendet werden können. Wenn der Filter nicht erfolgreich registriert wurde,

Was bedeutet Stream unter Linux? Was bedeutet Stream unter Linux? Mar 17, 2023 am 09:55 AM

Unter Linux bedeutet Stream einen Datenfluss, bei dem es sich um eine Zeichenfolge handelt, die in einer bestimmten Reihenfolge gelesen wird. Die Richtung des Datenflusses ist also die Lesereihenfolge des Datenflusses. Der Vorgang, bei dem das Linux-System die Ausgabeergebnisse importiert, nachdem die Daten in andere Dateien eingelesen wurden, wird als umgeleiteter Datenfluss bezeichnet. Nachdem ein Befehl unter Linux eingegeben und ausgeführt wurde, werden zwei Ergebnisse auf dem Bildschirm angezeigt: Das Ergebnis des erfolgreichen Vorgangs ist die Standardausgabe, und das Ergebnis des fehlgeschlagenen Vorgangs ist die Standardfehlerausgabe auf dem Bildschirm angezeigt und über den Datenfluss umgeleitet. Sie können es in anderen Dateien speichern.

So filtern und sortieren Sie Daten in der Vue-Technologieentwicklung So filtern und sortieren Sie Daten in der Vue-Technologieentwicklung Oct 09, 2023 pm 01:25 PM

So filtern und sortieren Sie Daten in der Vue-Technologieentwicklung. In der Vue-Technologieentwicklung sind das Filtern und Sortieren von Daten sehr häufige und wichtige Funktionen. Durch Datenfilterung und -sortierung können wir die benötigten Informationen schnell abfragen und anzeigen und so die Benutzererfahrung verbessern. In diesem Artikel wird das Filtern und Sortieren von Daten in Vue vorgestellt und spezifische Codebeispiele bereitgestellt, um den Lesern zu helfen, diese Funktionen besser zu verstehen und zu verwenden. 1. Datenfilterung Datenfilterung bezieht sich auf das Herausfiltern von Daten, die den Anforderungen basierend auf bestimmten Bedingungen entsprechen. In Vue können wir comp bestehen

In PHP stellt die FILTER_VALIDATE_URL-Konstante den Filter dar, der zum Validieren von URLs verwendet wird In PHP stellt die FILTER_VALIDATE_URL-Konstante den Filter dar, der zum Validieren von URLs verwendet wird Sep 14, 2023 am 10:37 AM

Die FILTER_VALIDATE_URL-Konstante wird zur Validierung von URLs verwendet. Das Flag FILTER_FLAG_SCHEME_REQUIRED-URL muss RFC-konform sein. FILTER_FLAG_HOST_REQUIRED-URL muss den Hostnamen enthalten. FILTER_FLAG_PATH_REQUIRED-URL muss einen Pfad nach dem Domänennamen haben. FILTER_FLAG_QUERY_REQUIRED-URL muss eine Abfragezeichenfolge haben. Rückgabewert FILTER_VALIDATE_URL

Wie die Java Stream API Ihren Code verbessert Wie die Java Stream API Ihren Code verbessert May 14, 2023 pm 06:22 PM

Vorwort JavaStream ist ein leistungsstarkes Datenverarbeitungstool, das Entwicklern dabei helfen kann, Datenströme schnell und effizient zu verarbeiten und umzuwandeln. Die Verwendung von Stream-Operationen kann den Code erheblich vereinfachen, ihn lesbarer und wartbarer machen und dadurch die Entwicklungseffizienz verbessern. filter(): Behält Elemente bei, die die Bedingungen basierend auf dem angegebenen Prädikat erfüllen. map(): Ordnet jedes Element gemäß der angegebenen Funktion zu und generiert einen neuen Stream. flatMap(): Ordnet jedes Element einem Stream zu und verkettet diese Streams dann zu einem Stream. unique(): Gibt einen deduplizierten Stream zurück. sorted(): für Stre

Filterfunktion in Vue3: Daten elegant verarbeiten Filterfunktion in Vue3: Daten elegant verarbeiten Jun 18, 2023 pm 02:46 PM

Filterfunktionen in Vue3: Eleganter Umgang mit Daten Vue ist ein beliebtes JavaScript-Framework mit einer großen Community und einem leistungsstarken Plug-in-System. In Vue ist die Filterfunktion ein sehr praktisches Werkzeug, mit dem wir Daten in Vorlagen verarbeiten und formatieren können. Es gab einige Änderungen an den Filterfunktionen in Vue3. In diesem Artikel werden wir uns eingehend mit den Filterfunktionen in Vue3 befassen und lernen, wie man sie für den eleganten Umgang mit Daten verwendet. Was ist eine Filterfunktion? In Vue ist die Filterfunktion

See all articles