代码:
<?php set_time_limit(0); ini_set('memory_limit', '-1'); //error_reporting(E_ALL); //ini_set('display_errors', 0); /** +---------------------------------- * UMD编码,文本转umd文件 +---------------------------------- */ class UMD { public $bookinfo = array ( "id" => 0, "title" => "", "author" => "xuxb", "year" => "0", "month" => "0", "day" => "0", "sort" => "", "publisher" => "", "seller" => "", "cover" => "" ); public $chapters = array(); public $chaptercount = 0; public $articlelen = 0; public $chaptitlelen = 0; public $charset = "GBK"; public $handle; public $exts = 'txt|php|java|c|pl|py|conf|yaml|js|htm|html|css|jsp|h|cpp'; public $result = []; function __construct() { $this->bookinfo['year'] = date("Y"); $this->bookinfo['month'] = date("n"); $this->bookinfo['day'] = date("j"); } /** * 设置书籍编码 * * @param String $charset */ function setCharset($charset) { $this->charset = $charset; } /** * 设置添加书籍头信息 * * @param Array $bookinfo */ function addBookInfo($bookinfo = array()) { //echo "addBookInfo-------->" . print_r($bookinfo, true)."\n"; foreach($this->bookinfo as $key => $value) { if(isset($bookinfo[$key])) { $this->bookinfo[$key] = $bookinfo[$key]; } if(($key != "id") && ($this->charset != "UCS")) { $this->bookinfo[$key] = iconv($this->charset,"UCS-2LE//IGNORE",$this->bookinfo[$key]); } } } /** * 设置添加章节 * * @param String $c_title * @param String $c_content */ function addChapter($c_title,$c_content) { //echo "addChapter-------->c_title:{$c_title}, c_content:{$c_content}\n"; if ( $this->charset != "UCS" ) { $c_title = iconv($this->charset,"UCS-2LE//IGNORE",$c_title); $c_content = iconv($this->charset,"UCS-2LE//IGNORE",$c_content); } $this->chapters[$this->chaptercount] = array ( "title" => $c_title, "content" => $c_content ); ++$this->chaptercount; $this->chaptitlelen += strlen($c_title); $this->articlelen += strlen($c_content); } /** * 从文件夹设置添加章节 * * @param String $c_title * @param String $c_content */ function addChapterFromDir($dirPath, $pre = '') { //echo "addChapterFromDir-------->dirPath:{$dirPath}, pre:{$pre}\n"; if(is_file($dirPath)){ return $this->addChapterFromFile($dirPath, $pre); } elseif(is_dir($dirPath) === false){ return false; } $files = $this->listTxtFiles($dirPath); if(!isset($files) || !is_array($files) || empty($files)){ return false; } foreach($files as $key=>$val) { $this->addChapterFromFile($val, $pre); } return true; } /** * 从文件夹设置添加章节 * * @param String $c_title * @param String $c_content */ function addChapterFromFile($filePath, $pre='') { if(is_file($filePath) === false || empty($pre)){ echo "addChapterFromFile is fail-------->filePath:{$filePath}, pre:{$pre}\n"; return false; } $filePath = str_replace("\\", "/", $filePath); $fileParts = preg_split("/\//", $filePath); $fileName = $fileParts[sizeof($fileParts)-1]; $chraptParts = preg_split('/\./', $fileName); $chraptName = preg_replace("/{$this->exts}/", "", strtolower($chraptParts[0])); $filecoding = $this->detect_encoding($filePath); $contents = trim($this->readFileContent($filePath)); //需要转换时增加 if($filecoding != 'GBK'){ $contents = iconv($filecoding, 'GBK//IGNORE', $contents); } //echo "contents: {$contents}\n"; //exit; $this->addChapter(($pre ? '['.$pre.']' : ''), $contents); return true; } /** * 从文件夹设置添加章节 * * @param String $c_title * @param String $c_content */ function addChapterFromPath($path) { //echo "addChapterFromPath-------->path:{$path}\n"; if(is_file($path) === true) { $this->addChapterFromFile($path); } elseif(is_dir($path) === true) { $this->addChapterFromDir($path); } return false; } /** * 读取文件内容 * * @param String $c_title * @param String $c_content */ function readFileContent($fileName) { if(is_file($fileName) === false) { return false; } $fh = @fopen($fileName, "r"); $contents = @fread($fh, filesize($fileName)); @fclose($fh); return $contents; } /** * 获取某个目录下面的txt文件 * * @param Int $fontSize * @param Int $screenWidth * @param Int $PID */ function listTxtFiles($txtDir) { //echo "listTxtFiles-------->txtDir:{$txtDir}\n"; if(is_dir($txtDir) === false) { return false; } $txtDir = str_replace("\\", "/", $txtDir); $dh = @opendir($txtDir); while(($file = @readdir($dh)) !== false) { if(stripos('.', $file) === false){} else{continue;} $fileParts = preg_split('/\./', $file); $fileExt = $fileParts[sizeof($fileParts)-1]; if(!in_array(strtolower($fileExt), explode('|', $this->exts))){continue;} $result[] = $txtDir .'/'. $file; } @closedir($dh); return $result; } /** * 获取某个目录下面的txt文件 * * @param Int $fontSize * @param Int $screenWidth * @param Int $PID */ function listDirs($txtDir) { //echo "listDirs-------->txtDir:{$txtDir}\n"; $txtDir = str_replace("\\", "/", $txtDir); if(!is_dir($txtDir)){ //echo "listDirs.is_dir-------->false\n"; $this->result[] = $txtDir .'/'. $file; } else{ //echo "listDirs-------->txtDir:{$txtDir}\n"; $dh = opendir($txtDir); $i = 1; while(($file = readdir($dh)) !== false){ if($file == '.' || $file == '..'){continue;} //echo "listDirs.readdir-------->file{$i}:{$file}\n"; $i++; if(is_dir($txtDir .'/'. $file)){ $this->listDirs($txtDir .'/'. $file); } else{ $this->result[] = $txtDir .'/'. $file; } } closedir($dh); } } /** * 获取路径 * * @param String $string * @param Int $node * @return String */ function getPath($filePath) { $filePath = trim($filePath); $filePath = str_replace("\\", '/', $filePath); while($filePath[strlen($filePath)-1] == '/') { $fileArr = preg_split('/\//', $filePath); unset($fileArr[sizeof($fileArr)-1]); $filePath = join('/', $fileArr); } while(stripos($filePath, '//') > 0) { $filePath = str_replace('//', '/', $filePath); } //echo "getPath-------->{$filePath}\n"; return $filePath; } /** * 获取文件名 * * @param String $string * @param Int $node * @return String */ function getName($filePath) { $filePath = $this->getPath($filePath); $filePath = rtrim($filePath, '/'); if(is_dir($filePath)){ if(stripos($filePath, '/') === false){ $bookName = str_replace(':', '', dirname($filePath)); } else{ $filePats = preg_split('/\//', $filePath); $bookName = $filePats[sizeof($filePats) - 1]; $bookName = str_replace(':', '', $bookName); } } else{ $filePats = preg_split('/\/|\./', $filePath); $bookName = $filePats[sizeof($filePats) - 2]; $bookName = str_replace(':', '', $bookName); } //echo "getName-------->{$filePath}\n"; return $bookName; } /** * 写入简介及其他相关信息 * * @param String $string * @param Int $node * @return String */ function makeInfo($string,$node) { $data = chr(35).chr($node).chr(0).chr(0); $data .= $this->dec2hex(strlen($string) + 5,1); $data .= $string; return $data; } /** * 十进制转十六进制 * * @param String $string * @param Int $length * @return String */ function dec2hex($string,$length) { $data = ""; $length *= 2; $c_string = substr(sprintf("%0".$length."s",dechex($string)),0 - $length); for ($i = 0;$i < $length;$i += 2) { $data = chr(hexdec(substr($c_string,$i,2))).$data; } return $data; } /** * 写入章节偏移量 * * @param Int $fontSize * @param Int $screenWidth * @param Int $PID */ function writePageOffset($fontSize,$screenWidth,$PID) { $h = mt_rand(28672,32767); $content_len = $this->articlelen + $this->chaptercount * 2; $data = pack('H*',"2387"); $data .= pack('n',$PID); $data .= chr(0x0B); $data .= chr($fontSize).chr($screenWidth); $data .= $this->dec2hex($h,4); $data .= chr(36); $data .= $this->dec2hex($h,4); $random = 17; $data .= $this->dec2hex($random,4); $random = 0; $data .= $this->dec2hex($random,4); $data .= $this->dec2hex($content_len,4); //$data .= $this->dec2hex(floor($content_len / 2),4); fwrite($this->handle,$data,strlen($data)); unset($data); } /** * 编译生成UMD * * @param String $filename * @return Boolean */ function makeUmd($filename) { //echo "makeUmd-------->{$filename}\n"; $this->handle = fopen($filename,"wb"); if(!$this->handle) { return false; } flock($this->handle,LOCK_EX); $data = ""; $data .= pack('H*',"899B9ADE"); //头 umd文件标志 $data .= pack('H*',"230100000801"); //0x01--文件开始 $data .= $this->dec2hex(mt_rand(1025,32767),2); $data .= $this->makeInfo($this->bookinfo['title'],2); //0x02--标题 $data .= $this->makeInfo($this->bookinfo['author'],3); //0x03--作者 $data .= $this->makeInfo($this->bookinfo['year'],4); //0x04--年 $data .= $this->makeInfo($this->bookinfo['month'],5); //0x05--月 $data .= $this->makeInfo($this->bookinfo['day'],6); //0x06--日 $data .= $this->makeInfo($this->bookinfo['sort'],7); //0x07--小说类型 $data .= $this->makeInfo($this->bookinfo['publisher'],8); //0x08--出版商 $data .= $this->makeInfo($this->bookinfo['seller'],9); //0x09--零售商 fwrite($this->handle,$data,strlen($data)); //0x0b--内容长度 $data = ""; $data .= pack('H*',"230B000009"); $data .= $this->dec2hex($this->articlelen + $this->chaptercount * 2,4); //0x83--章节偏移 写入章节数 $data .= pack('H*',"2383000109"); $random = mt_rand(12288,16383); $data .= $this->dec2hex($random,4); $data .= pack('H*',"24"); $data .= $this->dec2hex($random,4); $random = $this->chaptercount * 4 + 9; $data .= $this->dec2hex($random,4); $chapteroffset = 0; foreach($this->chapters as $key => $value) { $data .= $this->dec2hex($chapteroffset,4); $chapteroffset += strlen($value['content']) + 2; } //0x84--章节标题,正文 $data .= pack('H*',"2384000109"); $random = mt_rand(16384,20479); $data .= $this->dec2hex($random,4); $data .= pack('H*',"24"); $data .= $this->dec2hex($random,4); $random = 9 + $this->chaptitlelen + $this->chaptercount; $data .= $this->dec2hex($random,4); foreach($this->chapters as $key => $value) { $random = strlen($value['title']); $data .= $this->dec2hex($random,1); $data .= $value['title']; } fwrite($this->handle,$data,strlen($data)); $ss = 0; $oo = 32768; $chapstr = ""; foreach($this->chapters as $key => $value) { $chapstr .= $value['content'].chr(41).chr(32); } $chap_len = strlen($chapstr); $maximum = ceil($chap_len / $oo); $num_1 = mt_rand(0,$maximum - 1); $num_2 = mt_rand(0,$maximum - 1); $aa = array(); for($i = 0;$i < $maximum;++$i) { $data = ""; $data .= chr(36); $numrand = mt_rand(4.02653e+009,4.29497e+009); $aa[$i] = $numrand; $data .= $this->dec2hex($numrand,4); $c_chapstr = substr($chapstr,$ss,$oo); $ss += $oo ; $z_chapstr = gzcompress($c_chapstr); $random = 9 + strlen($z_chapstr); $data .= $this->dec2hex($random,4); $data .= $z_chapstr ; if($i == $num_1) { $data .= pack('H*',"23F100001500000000000000000000000000000000"); } if ($i == $num_2) { $data .= pack('H*',"230A000009"); $data .= $this->dec2hex($this->bookinfo['id'] + 268435456,4); } fwrite($this->handle,$data,strlen($data)); } //0x81--正文写入完毕 $data = ""; $data .= pack('H*',"2381000109"); $random = mt_rand(8192,12287); $data .= $this->dec2hex($random,4); $data .= chr(36); $data .= $this->dec2hex($random,4); $random = 9 + $maximum * 4; $data .= $this->dec2hex($random,4); for($i = 0;$i < $maximum;++$i) { $data .= $this->dec2hex($aa[$i],4); } fwrite($this->handle,$data,strlen($data)); //0x82--封面 $data = ""; if(!empty($this->bookinfo['cover']) || is_file($this->bookinfo['cover'])) { $data .= pack('H*',"238200011001"); $random = mt_rand(4096,8191); $data .= $this->dec2hex($random,4); $data .= chr(36); $data .= $this->dec2hex($random,4); $coverstream = file_get_contents($this->bookinfo['cover']); $random = strlen($coverstream) + 9; $data .= $this->dec2hex($random,4); $data .= $coverstream; fwrite($this->handle,$data,strlen($data)); $data = ""; } //0x87--PageOffset $this->writePageOffset(0x10,0xD0,0x01); $this->writePageOffset(0x10,0xB0,0x01); $this->writePageOffset(0x0C,0xD0,0x01); $this->writePageOffset(0x0C,0xB0,0x01); $this->writePageOffset(0x0A,0xA6,0x05); //0x0c--文件结束 $data .= pack('H*',"230C000109"); $random = 4 + strlen($data) + ftell($this->handle); $data .= $this->dec2hex($random,4); fwrite($this->handle,$data,strlen($data)); unset($data); flock($this->handle,LOCK_UN); fclose($this->handle); @chmod($filename,0755); return true; } /** * 检测文件编码 * @param string $file 文件路径 * @return string|null 返回 编码名 或 null */ function detect_encoding($file) { $list = array('GBK', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'ISO-8859-1'); $str = file_get_contents($file); foreach ($list as $item) { $tmp = mb_convert_encoding($str, $item, $item); if (md5($tmp) == md5($str)) { return $item; } } return null; } /** * 自动解析编码读入文件 * @param string $file 文件路径 * @param string $charset 读取编码 * @return string 返回读取内容 */ function auto_read($file, $charset='UTF-8') { $list = array('GBK', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'ISO-8859-1'); $str = file_get_contents($file); foreach ($list as $item) { $tmp = mb_convert_encoding($str, $item, $item); if (md5($tmp) == md5($str)) { return mb_convert_encoding($str, $charset, $item); } } return ""; } } //测试效果 $filePath = isset($argv[1]) && $argv[1] ? trim($argv[1]) : './xz'; if($filePath == ''){ echo "USAGE:php ".__FILE__." [PATH]..."; exit; } if(file_exists($filePath) === false){ echo "PATH:$filePath is not exists..."; exit; } $umd = new UMD(); $filePath = $umd->getPath($filePath); $bookName = $umd->getName($filePath); echo "filePath: {$filePath}\n"; echo "bookName: {$bookName}\n"; //exit; $umd->addBookInfo(array('title'=>$bookName)); if(is_dir($filePath)){ $umd->listDirs($filePath);//echo "目录下有这些文件:".print_r($dirs, true)."\n"; //print_r($umd->result); foreach($umd->result as $dir){ $tmps = explode('/', $dir); $tmps = $tmps[count($tmps)-1]; $tmps = explode('.', $tmps); unset($tmps[count($tmps)-1]); $chraptName = implode('.', $tmps); $chraptName = preg_replace("/\[|\]|【|】|(|)/", '', $chraptName); $chraptName = preg_replace("/\.\./", '.', $chraptName); $chraptName = trim($chraptName, '.'); //$umd->addChapter('['.$chraptName.']', ''); echo "dir: {$dir}\n"; echo "chraptName: {$chraptName}\n"; $umd->addChapterFromFile($dir, $chraptName); } } else{ $umd->addChapterFromFile($filePath, $bookName); } $umd->makeUmd($bookName . '.umd');
执行示例:
标签:return,filePath,random,param,umd,版本,dec2hex,php,data From: https://www.cnblogs.com/xuxiaobo/p/17105147.html