php读取rtf文件如何读取字体_php读取rtf字体信息法【技巧】

9次阅读

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

php读取rtf文件如何读取字体_php读取rtf字体信息法【技巧】

PHP 本身不原生支持 RTF 文件解析,更不会直接提取字体信息;要读取 RTF 中的字体(如 f0fswiss Helveticaf1froman Times New Roman),需手动解析 RTF 控制字。核心思路是:**跳过控制符和组结构,提取 fN 定义及后续的字体名称声明(fNfnamefNfroman 等)**。

理解 RTF 字体定义的基本结构

RTF 中字体通过 fonttbl 控制字定义,格式类似:

{fonttbl{f0fswissfcharset0 Helvetica;}{f1fromanfcharset0 Times New Roman;}}

关键点:

  • f0f1 是字体 ID,用于正文中标记(如 f0fs24 Hello
  • fswissfroman 是字体族标识(非名称),实际名称在分号前,如 HelveticaTimes New Roman
  • 字体名可能含空格、括号或 Unicode 转义(如 'e9 表示 é),需按 RTF 规则解码

用正则 + 状态机粗略提取字体表

适用于格式规范、无嵌套错误的 RTF(如 word 生成的基础文档)。不依赖外部库,轻量可行:

立即学习PHP免费学习笔记(深入)”;

  • 先用 file_get_contents() 读取文件,确保编码为 ANSI 或 UTF-8(RTF 头部 ansicpg936 等提示代码页)
  • 用正则定位 fonttbl{...} 区域(注意大括号嵌套,建议用简单匹配+模拟,或用 preg_match('/\\fonttbl{([^}]*)}/i', $rtf, $matches) 初筛)
  • 对匹配内容逐字符解析:识别 fd+ 后紧跟的 f[swiss|roman|modern|...] 或直接字体名(直到分号或空格)
  • 示例片段提取逻辑:

$pattern = '/\\f(d+)\\f[^;]+?\\fcharsetd+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)
  • 字体名中若含 '(撇号)或 ,需在正则中转义或预清理

更稳方案:用现成解析器(推荐)

手工解析易出错,尤其面对复杂格式。可考虑:

  • rtf-htmlphpgitHub 开源):将 RTF 转 HTML,再用 dom 解析 或内联样式
  • PHPWord:支持读取部分 RTF(需开启扩展),通过 PhpWordReaderRTF 获取段落样式,间接推断字体
  • 调用系统命令(linux/macOS):unrtf --textcatdoc 提取纯文本,但会丢失字体信息——仅适合不需要字体的场景

text=ZqhQzanResources