项目需求:现在有一个音频文件上传的功能,在上传后PHP需要获取这个音频文件的相关信息,例如:时长等,由于这个文件是放在买的空间上的,没有像ffmpeg这样的扩展来处理,那么PHP能不能获取到这些信息?
下面是之前在项目中用到的一个用PHP进行音频文件头部信息的读取与写入操作的实现,主要针对 WMA 和 MP3 两种格式,供参考。
<?php // AudioExif.class.php // 用PHP进行音频文件头部信息的读取与写入 // 目前只支持 WMA 和 MP3 两种格式, 只支持常用的几个头部信息 // // 写入信息支持: Title(名称), Artist(艺术家), Copyright(版权), Description (描述) // Year(年代), Genre (流派), AlbumTitle (专辑标题) // 其中 mp3 和 wma 略有不同, 具体返回的信息还可能更多, 但只有以上信息可以被写入 // mp3 还支持 Track (曲目编号写入) // 对于 MP3 文件支持 ID3v1也支持ID3v2, 读取时优先 v2, 写入时总是会写入v1, 必要时写入v2 // // 用法说明: (由于 wma 使用 Unicode 存取, 故还需要 mb_convert_encoding() 扩展 // 返回数据及写入数据均为 ANSI 编码, 即存什么就显示什么 (中文_GB2312) // // require (\'AudioExif.class.php\'); // $AE = new AudioExif; // $file = \'/path/to/test.mp3\'; // // 1. 检查文件是否完整 (only for wma, mp3始终返回 true) // // $AE->CheckSize($file); // // 2. 读取信息, 返回值由信息组成的数组, 键名解释参见上方 // // print_r($AE->GetInfo($file)); // // 3. 写入信息, 第二参数是一个哈希数组, 键->值, 支持的参见上方的, mp3也支持 Track // 要求第一参数的文件路径可由本程序写入 // $pa = array(\'Title\' => \'新标题\', \'AlbumTitle\' => \'新的专辑名称\'); // $AE->SetInfo($file, $pa); // // 其它: 该插件花了不少时间搜集查找 wma及mp3 的文件格式说明文档与网页, 希望对大家有用. // 其实网上已经有不少类似的程序, 但对 wma 实在太少了, 只能在 win 平台下通过 M$ 的 // API 来操作, 而 MP3 也很少有可以在 unix/linux 命令行操作的, 所以特意写了这个模块 // // 如果发现 bug 或提交 patch, 或加以改进使它更加健壮, 请告诉我. // (关于 ID3和Wma的文件格式及结构 在网上应该都可以找到参考资料) // if (!extension_loaded(\'mbstring\')){ trigger_error(\'PHP Extension module `mbstring` is required for AudioExif\', E_USER_WARNING); return true; } // the Main Class class AudioExif{ // public vars var $_wma = false; var $_mp3 = false; // Construct function AudioExif() { // nothing to do } // check the filesize function CheckSize($file) { $handler = &$this->_get_handler($file); if (!$handler) return false; return $handler->check_size($file); } // get the infomations function GetInfo($file) { $handler = &$this->_get_handler($file); if (!$handler) return false; return $handler->get_info($file); } // write the infomations function SetInfo($file, $pa) { if (!is_writable($file)) { trigger_error(\'AudioExif: file `\' . $file . \'` can not been overwritten\', E_USER_WARNING); return false; } $handler = &$this->_get_handler($file); if (!$handler) return false; return $handler->set_info($file, $pa); } // private methods function &_get_handler($file) { $ext = strtolower(strrchr($file, \'.\')); $ret = false; if ($ext == \'.mp3\') { // MP3 $ret = &$this->_mp3; if (!$ret) $ret = new _Mp3Exif(); } else if ($ext == \'.wma\') { // wma $ret = &$this->_wma; if (!$ret) $ret = new _WmaExif(); } else { // unknown trigger_error(\'AudioExif not supported `\' . $ext . \'` file.\', E_USER_WARNING); } return $ret; } } // DBCS => gb2312 function dbcs_gbk($str) { // strip the last \"\\0\\0\" $str = substr($str, 0, -2); return mb_convert_encoding($str, \'GBK\', \'UCS-2LE\'); } // gb2312 => DBCS function gbk_dbcs($str) { $str = mb_convert_encoding($str, \'UCS-2LE\', \'GBK\'); $str .= \"\\0\\0\"; return $str; } // file exif class _AudioExif { var $fd; var $head; var $head_off; var $head_buf; // init the file handler function _file_init($fpath, $write = false) { $mode = ($write ? \'rb+\' : \'rb\'); $this->fd = @fopen($fpath, $mode); if (!$this->fd) { trigger_error(\'AudioExif: `\' . $fpath . \'` can not be opened with mode `\' . $mode . \'`\', E_USER_WARNING); return false; } $this->head = false; $this->head_off = 0; $this->head_buf = \'\'; return true; } // read buffer from the head_buf & move the off pointer function _read_head_buf($len) { if ($len <= 0) return NULL; $buf = substr($this->head_buf, $this->head_off, $len); $this->head_off += strlen($buf); return $buf; } // read one short value function _read_head_short() { $ord1 = ord(substr($this->head_buf, $this->head_off, 1)); $ord2 = ord(substr($this->head_buf, $this->head_off+1, 1)); $this->head_off += 2; return ($ord1 + ($ord2<<8)); } // save the file head function _file_save($head, $olen, $nlen = 0) { if ($nlen == 0) $nlen = strlen($head); if ($nlen == $olen) { // shorter flock($this->fd, LOCK_EX); fseek($this->fd, 0, SEEK_SET); fwrite($this->fd, $head, $nlen); flock($this->fd, LOCK_UN); } else { // longer, buffer required $stat = fstat($this->fd); $fsize = $stat[\'size\']; // buf required (4096?) 应该不会 nlen - olen > 4096 吧 $woff = 0; $roff = $olen; // read first buffer flock($this->fd, LOCK_EX); fseek($this->fd, $roff, SEEK_SET); $buf = fread($this->fd, 4096); // seek to start fseek($this->fd, $woff, SEEK_SET); fwrite($this->fd, $head, $nlen); $woff += $nlen; // seek to woff & write the data do { $buf2 = $buf; $roff += 4096; if ($roff < $fsize) { fseek($this->fd, $roff, SEEK_SET); $buf = fread($this->fd, 4096); } // save last buffer $len2 = strlen($buf2); fseek($this->fd, $woff, SEEK_SET); fwrite($this->fd, $buf2, $len2); $woff += $len2; } while ($roff < $fsize); ftruncate($this->fd, $woff); flock($this->fd, LOCK_UN); } } // close the file function _file_deinit() { if ($this->fd) { fclose($this->fd); $this->fd = false; } } } // wma class class _WmaExif extends _AudioExif { var $items1 = array(\'Title\', \'Artist\', \'Copyright\', \'Description\', \'Reserved\'); var $items2 = array(\'Year\', \'Genre\', \'AlbumTitle\'); // check file size (length) maybe invalid file function check_size($file) { $ret = false; if (!$this->_file_init($file)) return true; if ($this->_init_header()) { $buf = fread($this->fd, 24); $tmp = unpack(\'H32id/Vlen/H8unused\', $buf); if ($tmp[\'id\'] == \'3626b2758e66cf11a6d900aa0062ce6c\') { $stat = fstat($this->fd); $ret = ($stat[\'size\'] == ($this->head[\'len\'] + $tmp[\'len\'])); } } $this->_file_deinit(); return $ret; } // set info (save the infos) function set_info($file, $pa) { // check the pa settype($pa, \'array\'); if (!$this->_file_init($file, true)) return false; if (!$this->_init_header()) { $this->_file_deinit(); return false; } // parse the old header & generate the new header $head_body = \'\'; $st_found = $ex_found = false; $head_num = $this->head[\'num\']; while (($tmp = $this->_get_head_frame()) && ($head_num > 0)) { $head_num--; if ($tmp[\'id\'] == \'3326b2758e66cf11a6d900aa0062ce6c\') { // Standard Info // 1-4 $st_found = true; $st_body1 = $st_body2 = \'\'; $lenx = unpack(\'v5\', $this->_read_head_buf(10)); $tmp[\'len\'] -= 34; // 10 + 24 for ($i = 0; $i < count($this->items1); $i++) { $l = $lenx[$i+1]; $k = $this->items1[$i]; $tmp[\'len\'] -= $l; $data = $this->_read_head_buf($l); if (isset($pa[$k])) $data = gbk_dbcs($pa[$k]); $st_body2 .= $data; $st_body1 .= pack(\'v\', strlen($data)); } // left length if ($tmp[\'len\'] > 0) $st_body2 .= $this->_read_head_buf($tmp[\'len\']); // save to head_body $head_body .= pack(\'H32VH8\', $tmp[\'id\'], strlen($st_body1 . $st_body2)+24, $tmp[\'unused\']); $head_body .= $st_body1 . $st_body2; $st_body2 .= $data; } // save to head_body $head_body .= pack(\'H32Va4\', \'3326b2758e66cf11a6d900aa0062ce6c\', strlen($st_body1 . $st_body2)+24, \'\'); $head_body .= $st_body1 . $st_body2; $this->head[\'num\']++; } // ex not found? if (!$ex_found) { $inum = 0; $et_body = \'\'; foreach ($this->items2 as $k) { $nbuf = gbk_dbcs(\'WM/\' . $k); $vbuf = (isset($pa[$k]) ? gbk_dbcs($pa[$k]) : \"\"); $et_body .= pack(\'v\', strlen($nbuf)) . $nbuf . pack(\'vv\', 0, strlen($vbuf)) . $vbuf; $inum++; } $head_body .= pack(\'H32Va4v\', \'40a4d0d207e3d21197f000a0c95ea850\', strlen($et_body)+26, \'\', $inum); $head_body .= $et_body; $this->head[\'num\']++; } // after save $new_len = strlen($head_body) + 30; $old_len = $this->head[\'len\']; if ($new_len < $old_len) { $head_body .= str_repeat(\"\\0\", $old_len - $new_len); $new_len = $old_len; } $tmp = $this->head; $head_buf = pack(\'H32VVVH4\', $tmp[\'id\'], $new_len, $tmp[\'len2\'], $tmp[\'num\'], $tmp[\'unused\']); $head_buf .= $head_body; $this->_file_save($head_buf, $old_len, $new_len); // close the file & return $this->_file_deinit(); return true; } // get info function get_info($file) { $ret = array(); if (!$this->_file_init($file)) return false; if (!$this->_init_header()) { $this->_file_deinit(); return false; } // get the data from head_buf $head_num = $this->head[\'num\']; // num of head_frame while (($tmp = $this->_get_head_frame()) && $head_num > 0) { $head_num--; if ($tmp[\'id\'] == \'3326b2758e66cf11a6d900aa0062ce6c\') { // Standard Info $lenx = unpack(\'v*\', $this->_read_head_buf(10)); for ($i = 1; $i <= count($this->items1); $i++) { $k = $this->items1[$i-1]; $ret[$k] = dbcs_gbk($this->_read_head_buf($lenx[$i])); } } else if ($tmp[\'id\'] == \'40a4d0d207e3d21197f000a0c95ea850\') { // Extended Info $inum = $this->_read_head_short(); $tmp[\'len\'] -= 26; while ($inum > 0 && $tmp[\'len\'] > 0) { // attribute name $nlen = $this->_read_head_short(); $nbuf = $this->_read_head_buf($nlen); // the flag & value length $flag = $this->_read_head_short(); $vlen = $this->_read_head_short(); $vbuf = $this->_read_head_buf($vlen); // update the XX $tmp[\'len\'] -= (6 + $nlen + $vlen); $inum--; $name = dbcs_gbk($nbuf); $k = substr($name, 3); if (in_array($k, $this->items2)) { // all is string value (refer to falg for other tags) $ret[$k] = dbcs_gbk($vbuf); } } } else { // skip only if ($tmp[\'len\'] > 24) $this->head_off += ($tmp[\'len\'] - 24); } } $this->_file_deinit(); return $ret; } // get the header? function _init_header() { fseek($this->fd, 0, SEEK_SET); $buf = fread($this->fd, 30); if (strlen($buf) != 30) return false; $tmp = unpack(\'H32id/Vlen/Vlen2/Vnum/H4unused\', $buf); if ($tmp[\'id\'] != \'3026b2758e66cf11a6d900aa0062ce6c\') return false; $this->head_buf = fread($this->fd, $tmp[\'len\'] - 30); $this->head = $tmp; return true; } // _get_head_frame() function _get_head_frame() { $buf = $this->_read_head_buf(24); if (strlen($buf) != 24) return false; $tmp = unpack(\'H32id/Vlen/H8unused\', $buf); return $tmp; } } // mp3 class (if not IDv2 then select IDv1) class _Mp3Exif extends _AudioExif { var $head1; var $genres = array(\'Blues\',\'Classic Rock\',\'Country\',\'Dance\',\'Disco\',\'Funk\',\'Grunge\',\'Hip-Hop\',\'Jazz\',\'Metal\',\'New Age\',\'Oldies\',\'Other\',\'Pop\',\'R&B\',\'Rap\',\'Reggae\',\'Rock\',\'Techno\',\'Industrial\',\'Alternative\',\'Ska\',\'Death Metal\',\'Pranks\',\'Soundtrack\',\'Euro-Techno\',\'Ambient\',\'Trip-Hop\',\'Vocal\',\'Jazz+Funk\',\'Fusion\',\'Trance\',\'Classical\',\'Instrumental\',\'Acid\',\'House\',\'Game\',\'Sound Clip\',\'Gospel\',\'Noise\',\'AlternRock\',\'Bass\',\'Soul\',\'Punk\',\'Space\',\'Meditative\',\'Instrumental Pop\',\'Instrumental Rock\',\'Ethnic\',\'Gothic\',\'Darkwave\',\'Techno-Industrial\',\'Electronic\',\'Pop-Folk\',\'Eurodance\',\'Dream\',\'Southern Rock\',\'Comedy\',\'Cult\',\'Gangsta\',\'Top 40\',\'Christian Rap\',\'Pop/Funk\',\'Jungle\',\'Native American\',\'Cabaret\',\'New Wave\',\'Psychadelic\',\'Rave\',\'Showtunes\',\'Trailer\',\'Lo-Fi\',\'Tribal\',\'Acid Punk\',\'Acid Jazz\',\'Polka\',\'Retro\',\'Musical\',\'Rock & Roll\',\'Hard Rock\',\'Unknown\'); // MP3 always return true function check_size($file) { return true; } // get info function get_info($file) { if (!$this->_file_init($file)) return false; $ret = false; if ($this->_init_header()) { $ret = ($this->head ? $this->_get_v2_info() : $this->_get_v1_info()); $ret[\'meta\'] = $this->_get_meta_info(); } $this->_file_deinit(); return $ret; } // set info function set_info($file, $pa) { if (!$this->_file_init($file, true)) return false; if ($this->_init_header()) { // always save v1 info $this->_set_v1_info($pa); // set v2 first if need $this->_set_v2_info($pa); } $this->_file_deinit(); return true; } // get the header information[v1+v2], call after file_init function _init_header() { $this->head1 = false; $this->head = false; // try to get ID3v1 first fseek($this->fd, -128, SEEK_END); $buf = fread($this->fd, 128); if (strlen($buf) == 128 && substr($buf, 0, 3) == \'TAG\') { $tmp = unpack(\'a3id/a30Title/a30Artist/a30AlbumTitle/a4Year/a28Description/CReserved/CTrack/CGenre\', $buf); $this->head1 = $tmp; } // try to get ID3v2 fseek($this->fd, 0, SEEK_SET); $buf = fread($this->fd, 10); if (strlen($buf) == 10 && substr($buf, 0, 3) == \'ID3\') { $tmp = unpack(\'a3id/Cver/Crev/Cflag/C4size\', $buf); $tmp[\'size\'] = ($tmp[\'size1\']<<21)|($tmp[\'size2\']<<14)|($tmp[\'size3\']<<7)|$tmp[\'size4\']; unset($tmp[\'size1\'], $tmp[\'size2\'], $tmp[\'size3\'], $tmp[\'size4\']); $this->head = $tmp; $this->head_buf = fread($this->fd, $tmp[\'size\']); } return ($this->head1 || $this->head); } // get v1 info function _get_v1_info() { $ret = array(); $tmpa = array(\'Title\', \'Artist\', \'Copyright\', \'Description\', \'Year\', \'AlbumTitle\'); foreach ($tmpa as $tmp) { $ret[$tmp] = $this->head1[$tmp]; if ($pos = strpos($ret[$tmp], \"\\0\")) $ret[$tmp] = substr($ret[$tmp], 0, $pos); } // count the Genre, [Track] if ($this->head1[\'Reserved\'] == 0) $ret[\'Track\'] = $this->head1[\'Track\']; else $ret[\'Description\'] .= chr($ret[\'Reserved\']) . chr($ret[\'Track\']); // Genre_idx $g = $this->head1[\'Genre\']; if (!isset($this->genres[$g])) $ret[\'Genre\'] = \'Unknown\'; else $ret[\'Genre\'] = $this->genres[$g]; // return the value $ret[\'ID3v1\'] = \'yes\'; return $ret; } // get v2 info function _get_v2_info() { $ret = array(); $items = array( \'TCOP\'=>\'Copyright\', \'TPE1\'=>\'Artist\', \'TIT2\'=>\'Title\', \'TRCK\'=> \'Track\', \'TCON\'=>\'Genre\', \'COMM\'=>\'Description\', \'TYER\'=>\'Year\', \'TALB\'=>\'AlbumTitle\'); while (true) { $buf = $this->_read_head_buf(10); if (strlen($buf) != 10) break; $tmp = unpack(\'a4fid/Nsize/nflag\', $buf); if ($tmp[\'size\'] == 0) break; $tmp[\'dat\'] = $this->_read_head_buf($tmp[\'size\']); // 0x6000 (11000000 00000000) if ($tmp[\'flag\'] & 0x6000) continue; // mapping the data if ($k = $items[$tmp[\'fid\']]) { // If first char is \"\\0\", just skip if (substr($tmp[\'dat\'], 0, 1) == \"\\0\") $tmp[\'dat\'] = substr($tmp[\'dat\'], 1); $ret[$k] = $tmp[\'dat\']; } } // reset the genre if ($g = $ret[\'Genre\']) { if (substr($g,0,1) == \'(\' && substr($g,-1,1) == \')\') $g = substr($g, 1, -1); if (is_numeric($g)) { $g = intval($g); $ret[\'Genre\'] = (isset($this->genres[$g]) ? $this->genres[$g] : \'Unknown\'); } } $ret[\'ID3v1\'] = \'no\'; return $ret; } // get meta info of MP3 function _get_meta_info() { // seek to the lead buf: 0xff $off = 0; if ($this->head) $off = $this->head[\'size\'] + 10; fseek($this->fd, $off, SEEK_SET); while (!feof($this->fd)) { $skip = ord(fread($this->fd, 1)); if ($skip == 0xff) break; } if ($skip != 0xff) return false; $buf = fread($this->fd, 3); if (strlen($buf) != 3) return false; $tmp = unpack(\'C3\', $buf); if (($tmp[1] & 0xf0) != 0xf0) return false; // get the meta info $meta = array(); // get mpeg version $meta[\'mpeg\'] = ($tmp[1] & 0x08 ? 1 : 2); $meta[\'layer\'] = ($tmp[1] & 0x04) ? (($tmp[1] & 0x02) ? 1 : 2) : (($tmp[1] & 0x02) ? 3 : 0); $meta[\'epro\'] = ($tmp[1] & 0x01) ? \'no\' : \'yes\'; // bit rates $bit_rates = array( 1 => array( 1 => array(0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0), 2 => array(0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0), 3 => array(0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0) ), 2 => array( 1 => array(0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0), 2 => array(0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0), 3 => array(0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0) ) ); $i = $meta[\'mpeg\']; $j = $meta[\'layer\']; $k = ($tmp[2]>>4); $meta[\'bitrate\'] = $bit_rates[$i][$j][$k]; // sample rates <采样率> $sam_rates = array(1=>array(44100,48000,32000,0), 2=>array(22050,24000,16000,0)); $meta[\'samrate\'] = $sam_rates[$i][$k]; $meta[\"padding\"] = ($tmp[2] & 0x02) ? \'on\' : \'off\'; $meta[\"private\"] = ($tmp[2] & 0x01) ? \'on\' : \'off\'; // mode & mode_ext $k = ($tmp[3]>>6); $channel_modes = array(\'stereo\', \'joint stereo\', \'dual channel\', \'single channel\'); $meta[\'mode\'] = $channel_modes[$k]; $k = (($tmp[3]>>4) & 0x03); $extend_modes = array(\'MPG_MD_LR_LR\', \'MPG_MD_LR_I\', \'MPG_MD_MS_LR\', \'MPG_MD_MS_I\'); $meta[\'ext_mode\'] = $extend_modes[$k]; $meta[\'copyright\'] = ($tmp[3] & 0x08) ? \'yes\' : \'no\'; $meta[\'original\'] = ($tmp[3] & 0x04) ? \'yes\' : \'no\'; $emphasis = array(\'none\', \'50/15 microsecs\', \'rreserved\', \'CCITT J 17\'); $k = ($tmp[3] & 0x03); $meta[\'emphasis\'] = $emphasis[$k]; return $meta; } // set v1 info function _set_v1_info($pa) { // ID3v1 (simpled) $off = -128; if (!($tmp = $this->head1)) { $off = 0; $tmp[\'id\'] = \'TAG\'; $tmp[\'Title\'] = $tmp[\'Artist\'] = $tmp[\'AlbumTitle\'] = $tmp[\'Year\'] = $tmp[\'Description\'] = \'\'; $tmp[\'Reserved\'] = $tmp[\'Track\'] = $tmp[\'Genre\'] = 0; } // basic items $items = array(\'Title\', \'Artist\', \'Copyright\', \'Description\', \'Year\', \'AlbumTitle\'); foreach ($items as $k) { if (isset($pa[$k])) $tmp[$k] = $pa[$k]; } // genre index if (isset($pa[\'Genre\'])) { $g = 0; foreach ($this->genres as $gtmp) { if (!strcasecmp($gtmp, $pa[\'Genre\'])) break; $g++; } $tmp[\'Genre\'] = $g; } if (isset($pa[\'Track\'])) $tmp[\'Track\'] = intval($pa[\'Track\']); // pack the data $buf = pack(\'a3a30a30a30a4a28CCC\', $tmp[\'id\'], $tmp[\'Title\'], $tmp[\'Artist\'], $tmp[\'AlbumTitle\'], $tmp[\'Year\'], $tmp[\'Description\'], 0, $tmp[\'Track\'], $tmp[\'Genre\']); flock($this->fd, LOCK_EX); fseek($this->fd, $off, SEEK_END); fwrite($this->fd, $buf, 128); flock($this->fd, LOCK_UN); } // set v2 info function _set_v2_info($pa) { if (!$this->head) { // insert ID3 return; // 没有就算了 /** $tmp = array(\'id\'=>\'ID3\',\'ver\'=>3,\'rev\'=>0,\'flag\'=>0); $tmp[\'size\'] = -10; // +10 => 0 $this->head = $tmp; $this->head_buf = \'\'; $this->head_off = 0; **/ } $items = array( \'TCOP\'=>\'Copyright\', \'TPE1\'=>\'Artist\', \'TIT2\'=>\'Title\', \'TRAC\'=>\'Track\', \'TCON\'=>\'Genre\', \'COMM\'=>\'Description\', \'TYER\'=>\'Year\', \'TALB\'=>\'AlbumTitle\'); $head_body = \'\'; while (true) { $buf = $this->_read_head_buf(10); if (strlen($buf) != 10) break; $tmp = unpack(\'a4fid/Nsize/nflag\', $buf); if ($tmp[\'size\'] == 0) break; $data = $this->_read_head_buf($tmp[\'size\']); if (($k = $items[$tmp[\'fid\']]) && isset($pa[$k])) { // the data should prefix by \"\\0\" [replace] $data = \"\\0\" . $pa[$k]; unset($pa[$k]); } $head_body .= pack(\'a4Nn\', $tmp[\'fid\'], strlen($data), $tmp[\'flag\']) . $data; } // reverse the items & set the new tags $items = array_flip($items); foreach ($pa as $k => $v) { if ($fid = $items[$k]) { $head_body .= pack(\'a4Nn\', $fid, strlen($v) + 1, 0) . \"\\0\" . $v; } } // new length $new_len = strlen($head_body) + 10; $old_len = $this->head[\'size\'] + 10; if ($new_len < $old_len) { $head_body .= str_repeat(\"\\0\", $old_len - $new_len); $new_len = $old_len; } // count the size1,2,3,4, no include the header // 较为变态的算法... :p (28bytes integer) $size = array(); $nlen = $new_len - 10; for ($i = 4; $i > 0; $i--) { $size[$i] = ($nlen & 0x7f); $nlen >>= 7; } $tmp = $this->head; //echo \"old_len : $old_len new_len: $new_len\\n\"; $head_buf = pack(\'a3CCCCCCC\', $tmp[\'id\'], $tmp[\'ver\'], $tmp[\'rev\'], $tmp[\'flag\'], $size[1], $size[2], $size[3], $size[4]); $head_buf .= $head_body; $this->_file_save($head_buf, $old_len, $new_len); }
以上所述就是本文的全部内容了,希望大家能够喜欢。
本文地址:https://www.stayed.cn/item/26609
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我