PHP不原生支持RTF字体解析,需手动提取\fonttbl中\fN定义及分号前的字体名,注意编码转换与Unicode转义,或使用rtf-html-php等现成解析器。

PHP 本身不原生支持 RTF 文件解析,更不会直接提取字体信息;要读取 RTF 中的字体(如 \f0\fswiss Helvetica、\f1\froman Times New Roman),需手动解析 RTF 控制字。核心思路是:**跳过控制符和组结构,提取 \fN 定义及后续的字体名称声明(\fN\fname 或 \fN\froman 等)**。
理解 RTF 字体定义的基本结构
RTF 中字体通过 \fonttbl 控制字定义,格式类似:
{\fonttbl{\f0\fswiss\fcharset0 Helvetica;}{\f1\froman\fcharset0 Times New Roman;}}
关键点:
-
\f0、\f1是字体 ID,用于正文中标记(如\f0\fs24 Hello) -
\fswiss、\froman是字体族标识(非名称),实际名称在分号前,如Helvetica、Times New Roman - 字体名可能含空格、括号或 Unicode 转义(如
'e9表示 é),需按 RTF 规则解码
用正则 + 状态机粗略提取字体表
适用于格式规范、无嵌套错误的 RTF(如 Word 生成的基础文档)。不依赖外部库,轻量可行:
立即学习“PHP免费学习笔记(深入)”;
- 先用
file_get_contents()读取文件,确保编码为 ANSI 或 UTF-8(RTF 头部\ansicpg936等提示代码页) - 用正则定位
\fonttbl{...}区域(注意大括号嵌套,建议用简单匹配+栈模拟,或用preg_match('/\\\\fonttbl\{([^}]*)\}/i', $rtf, $matches)初筛) - 对匹配内容逐字符解析:识别
\f\d+后紧跟的\f[swiss|roman|modern|...]或直接字体名(直到分号或空格) - 示例片段提取逻辑:
$pattern = '/\\\\f(\d+)\\\\f[^;]+?\\\\fcharset\d+\s+([^;]+);/i';
preg_match_all($pattern, $fonttbl_content, $fonts);
$fontMap = array_combine($fonts[1], array_map('trim', $fonts[2])); // ['0'=>'Helvetica', '1'=>'Times New Roman']
处理中文与编码问题
中文 RTF 常用 \ansicpg936(GBK)或 \uc1 + Unicode 转义('e4')。PHP 读取后需:
- 检查 RTF 头部
\ansicpg值,用mb_convert_encoding($text, 'UTF-8', 'GBK')转换(若为 936) - 替换 Unicode 转义:
preg_replace_callback("/'([0-9a-fA-F]{2})/", function($m) { return mb_chr(hexdec($m[1]), 'UTF-8'); }, $str) - 字体名中若含
'(撇号)或\,需在正则中转义或预清理
更稳方案:用现成解析器(推荐)
手工解析易出错,尤其面对复杂格式。可考虑:











