亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > PHP > 正文

PHP基于閉包思想實現的BT(torrent)文件解析工具實例詳解

2024-05-04 23:59:42
字體:
來源:轉載
供稿:網友

本文實例講述了PHP基于閉包思想實現的torrent文件解析工具。分享給大家供大家參考,具體如下:

PHP對靜態詞法域的支持有點奇怪,內部匿名函數必須在參數列表后面加上use關鍵字,顯式的說明想要使用哪些外層函數的局部變量。

function count_down($count){  return $func = function()    use($count,$func)  {    if(--$count > 0)      $func();    echo "wow/n";  };}$foo = count_down(3);$foo();

我本來是想這樣的。但是不行,會在第7行調用$func的時候報錯。

錯誤是Fatal error: Function name must be a string in - on line 7

反復試驗后發覺,外部的匿名函數應該通過引用傳值傳給內部,否則是不行的:

function count_down($count){  return $foo = function()    use(&$count,&$foo)  {    echo $count."/n";    if(--$count > 0)      $foo();  };}$foo = count_down(4);$foo();

像上面這樣寫就對了。

下面是另一種方法:

function count_down_again($count){  return function()use($count)  {    printf("wow %d/n",$count);    return --$count;  };}$foo = count_down_again(5);while($foo() >0);

不過,這段代碼有點小錯誤。編譯雖然沒錯,但是$foo函數每次返回的都是4.

也就是use關鍵字看上去像是支持靜態詞法域的,在這個例子上,它只是對外層函數使用的變量作了一個簡單拷貝。

讓我們稍微修改一下,把第3行的use($count)改為use(&$count):

function count_down_again($count){  return function()use(&$count)  {    printf("wow %d/n",$count);    return --$count;  };}$foo = count_down_again(5);while($foo() >0);

這樣才正確。

我個人使用的方式是基于類的,做成了類似下面的形式:

class Foo{  public function __invoke($count)  {    if($count > 0)      $this($count - 1);    echo "wow/n";  }}$foo = new Foo();$foo(4);

這樣做的行為也是正確的。

這樣不會像前一個例子那樣失去了遞歸調用的能力。

雖然這是一個類,但是只不過是在手動實現那些支持閉包和靜態詞法域的語言中,編譯器自動實現的動作。

其實今天早上,我本來準備用類scheme的風格寫一個解析器的??赡苌晕⑼睃c吧。scheme風格的函數式編程是這樣的:

function yet_another_count_down($func,$count){  $func($count);  if($count > 0)    yet_another_count_down($func,$count - 1);}yet_another_count_down(function($var){echo $var."/n";},6);

它不是很依賴靜態詞法域,雖然scheme對靜態詞法域的支持還是很不錯的。它主要還是利用了first-class-function。當然,這也是一種典型的閉包。

我實現的torrent解析工具的代碼如下:

<?php$file_name = '1.torrent';$file = fopen($file_name,'r');$nil = new Parser($file);//構造解析器$nil = $nil();//進行解析$pos = ftell($file);echo '讀取到文件位置'.sprintf('0x%08X',$pos)."/r/n";fseek($file,0,SEEK_END);echo '還剩下'.(ftell($file) - $pos).'字節未讀取'."/r/n";if(!feof($file)){  echo '文件還未結束,再讀一個字符:';  $ch = fgetc($file);  if(is_string($ch) && ereg('/w',$ch))  {    echo $ch."/r/n";  }  else  {    printf('0x%02X',$ch);    echo "/r/n";  }  echo '現在的文件位置是'.sprintf('0x%08X',ftell($file))."/r/n";  echo '文件'.(feof($file)?'已結束':'還未結束')."/r/n";}fclose($file);//解析器后面不再工作了,此時可以釋放文件指針了。$info = @$nil['value'][0]['info'];if(!$info){  echo '這是一個有效的B-Encoding文件,但它不是一個有效的種子文件';  exit();}$name = $info['name.utf-8'] ?$info['name.utf-8']:$info['name'];if(!$name){  echo '這是一個有效的B-Encoding文件,但它不是一個有效的種子文件';  exit();}echo $name."/r/n";if($info['files']){  $index = 0;  foreach($info['files'] as $f)  {    $index += 1;    $path = $f['path.utf8'] ?$f['path.utf8'] :$f['path'];    if(!$path)    {      echo '文件列表中的第'.$index."個文件不含目錄/r/n";      continue;    }    if(0 === strpos($path[0],"_____padding_file_"))continue;    $under_folder = false;    foreach($path as $item)    {      if($under_folder)      {        echo '/';      }else{        $under_folder = true;      }      echo $item;    }    echo "/r/n";  }}else{  echo "僅有一個文件/r/n";}class Parser{  private $_file;  public function __construct($file)  {    $this ->_file = $file;  }  public function __invoke($parent = array())  {    $ch = $this ->read();    switch($ch)    {    case 'i':      {        $n = $ch;        while(($ch = $this ->read()) != 'e')        {          if(!is_numeric($ch))          {            echo '在';            echo sprintf(                '0x%08X',ftell($this ->_file));            echo '解析數字時遇到錯誤',"/r/n";            echo '在i和e之間不應該出現非數字字符'."/r/n";            echo '意外的字符'.sprintf('0x%02X',$ch);            exit();          }          else          {            $n .= $ch;          }        }        $n += 0;        $offset = count($parent['value']);        $parent['value'][$offset] = $n;        return $parent;      }      break;    case 'd':      {        $node = array();        //這個$node變量作為字典對象準備加入到$parent的孩子節點中去        //$node['type'] = 'd';        while('e' != ($tmp = $this($node)))        {//每次給$node帶來一個新孩子          $node = $tmp;        }        $child_count = count($node['value']);        if($child_count % 2 != 0)        {          echo '解析結尾于';          echo sprintf('0x%08X',ftell($this ->_file));          echo '的字典時遇到錯誤:'."/r/n";          echo '字典的對象映射不匹配';          exit();        }        $product = array();        for($i = 0; $i < $child_count; $i += 2)        {          $key = $node['value'][$i];          $value = $node['value'][$i + 1];          if(!is_string($key))          {            echo '無效的字典結尾于';            echo sprintf('0x%08X',ftell($this ->_file));            echo ":/r/n";            echo '解析[k => v]配對時遇到錯誤,k應為字符串';            exit();          }          $product[$key] = $value;        }        /*         * 思想是這樣的:子節點想要加入父節點時,         * 往父節點的value數組添加。         * 當父節點收集好所需的信息后,         * 父節點自身再從它的value節點整合內容         * 對于字典和列表統一這樣處理會大大降低代碼量         */        $offset = count($parent['value']);        $parent['value'][$offset] = $product;        return $parent;      }      break;    case 'l';      {        $node = array();        while('e' != ($tmp = $this($node)))        {          $node = $tmp;        }        $offset = count($parent['value']);        $parent['value'][$offset] = $node['value'];        return $parent;      }      break;    case 'e':        return 'e';      break;    default:      {        if(!is_numeric($ch))        {          $this ->unexpected_character(            ftell($this ->_file) - 1,$ch);        }        $n = $ch;        while(($ch = $this ->read()) != ':')        {          $n .= $ch;          if(!is_numeric($n))          {            unexpected_character(              ftell($this ->_file) - 1,$ch);          }        }        $n += 0;        $str = '';        for(; $n > 0; --$n)        {          $str .= $this ->read();        }        $offset = count($parent['value']);        $parent['value'][$offset] = $str;        return $parent;      }      break;    }  }  /*   * read函數包裹了$this ->_file變量   */  function read()  {    if(!feof($this ->_file))    {      return fgetc($this ->_file);    }else{      echo '意外的文件結束';      exit();    }  }  /*   * unexpected_character函數接收2個參數   * 它用于指明腳本在何處遇到了哪個不合法的字符,   * 并在返回前終止腳本的運行。   */  function unexpected_character($pos,$val)  {    $hex_pos = sprintf("0x%08X",$pos);    $hex_val = sprintf("0x%02X",$val);    echo 'Unexpected Character At Position ';    echo $hex_pos.' , Value '.$hex_val."/r/n";    echo "Analysing Process Teminated.";    exit();  }}?>

這里很有趣的是,明明我對文件調用了fseek($file,0,SEEK_END);移動到文件末尾了,但是feof還是報告說文件沒有結束,并且fgetc返回一個0,而沒有報錯。但是此時文件實際上已經到末尾了。

希望本文所述對大家PHP程序設計有所幫助。


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91在线免费视频| 欧美激情va永久在线播放| 亚洲电影成人av99爱色| 中文字幕国产精品久久| 欧美乱妇高清无乱码| 日韩av在线精品| 国产精品永久在线| 成人中文字幕在线观看| 欧美xxxwww| 国产成人精品视频在线| 草民午夜欧美限制a级福利片| 在线观看久久久久久| 欧美激情在线观看| 日韩av中文字幕在线免费观看| 欧美精品videosex性欧美| 一道本无吗dⅴd在线播放一区| 日韩综合中文字幕| 国产日本欧美一区二区三区在线| 国产成人一区三区| 国产精品免费一区豆花| 96精品久久久久中文字幕| 国产精品第一第二| 日本一区二区三区在线播放| 午夜精品久久久久久99热| 欧美精品免费在线| 久久国产天堂福利天堂| 91成人福利在线| 国产性猛交xxxx免费看久久| 久久精品视频在线观看| 国产aaa精品| 26uuu久久噜噜噜噜| 日本欧美在线视频| 97热在线精品视频在线观看| 91亚洲精品在线| 91禁国产网站| 国产精品影院在线观看| 一区二区三区www| 欧美极品美女视频网站在线观看免费| 亚洲成人激情视频| 国产日产欧美精品| 亚洲一区二区福利| 这里精品视频免费| 国产日韩在线观看av| 日韩精品视频免费| 狠狠躁夜夜躁人人爽超碰91| 欧美性开放视频| 国产精品自拍网| 欧美性生交大片免网| 久久久伊人欧美| 国产精品v日韩精品| 亚洲影院色在线观看免费| 91精品久久久久久综合乱菊| 国产亚洲精品激情久久| 欧美xxxx14xxxxx性爽| 亚洲第一精品夜夜躁人人躁| 成人免费xxxxx在线观看| 欧美精品制服第一页| 亚洲第一天堂av| 奇门遁甲1982国语版免费观看高清| 久久久精品日本| 精品露脸国产偷人在视频| 欧美极品少妇xxxxⅹ裸体艺术| 久久精品视频在线| 日韩欧美aⅴ综合网站发布| 亚洲国模精品一区| 亚洲毛茸茸少妇高潮呻吟| 国产精品极品在线| 久久久伊人欧美| 亚洲精品女av网站| 久久中文字幕一区| 精品日韩中文字幕| 日韩在线视频免费观看| 亚洲日韩中文字幕| 亚洲韩国青草视频| 久久久久久高潮国产精品视| 91夜夜揉人人捏人人添红杏| 日本aⅴ大伊香蕉精品视频| 欧美激情精品久久久久久蜜臀| 久久夜色精品国产欧美乱| 亚洲jizzjizz日本少妇| 国产成+人+综合+亚洲欧美丁香花| 成人精品视频99在线观看免费| 国产精品久久色| 91久久精品国产91性色| 欧美日韩一区二区精品| 性亚洲最疯狂xxxx高清| 亚洲欧美国产另类| 国内精品美女av在线播放| 欧美成人精品在线观看| 亚洲人a成www在线影院| 欧美伊久线香蕉线新在线| 国产欧亚日韩视频| 亚洲深夜福利在线| 91久久在线观看| 国产91精品在线播放| 日本道色综合久久影院| 日韩美女视频在线观看| 久久久久久久久中文字幕| 亚洲欧美日韩精品久久奇米色影视| 亚洲欧美一区二区三区久久| 国产精品白嫩美女在线观看| 麻豆一区二区在线观看| 狠狠爱在线视频一区| 欧洲精品久久久| 久久久国产一区二区三区| 日韩av在线影院| 国产精品自产拍在线观看中文| 国产精品女主播视频| 国产成人精品在线视频| 欧美日韩中文字幕在线| 久久99热这里只有精品国产| 欧美日韩在线免费| 国产日韩欧美在线看| 国产欧美在线观看| 欧美激情视频在线免费观看 欧美视频免费一| 久久国产精品99国产精| 亚洲精品福利视频| 国产成人久久久| 97在线视频免费播放| 国产亚洲成精品久久| 91中文字幕在线观看| 亚洲精品久久久久久久久| 久久久亚洲影院| 日韩有码片在线观看| 久久久久久网站| 久久视频精品在线| 欧美性猛交xxxxx水多| 国产日产久久高清欧美一区| 91手机视频在线观看| 国内精品在线一区| 亚洲精品视频二区| 亚洲无限乱码一二三四麻| 人九九综合九九宗合| 久久久久久久亚洲精品| 精品久久久精品| 欧美性猛交xxxx乱大交蜜桃| 午夜剧场成人观在线视频免费观看| 91av成人在线| 色七七影院综合| 亚洲天天在线日亚洲洲精| 人人爽久久涩噜噜噜网站| 久久人人爽亚洲精品天堂| 欧美激情三级免费| 国外成人在线视频| 国产精品露脸自拍| 日韩国产一区三区| 欧美一级电影久久| 亚洲精品国产suv| 精品国模在线视频| 中文字幕精品久久| 中文字幕欧美日韩va免费视频| 欧美丰满少妇xxxxx做受| 成人黄色影片在线| 亚洲国产成人在线视频| 久久久久久久久久久免费精品| 欧美大片va欧美在线播放| 亚洲精品第一国产综合精品| 国产午夜精品久久久| 国产精品久久久久久久7电影| 久久久久久久久久国产| 久久久噜久噜久久综合| 蜜月aⅴ免费一区二区三区| 欧美重口另类videos人妖| 国产狼人综合免费视频|