惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
云风的 BLOG
云风的 BLOG
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Hacker News
The Hacker News
Martin Fowler
Martin Fowler
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
U
Unit 42
F
Full Disclosure
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Recorded Future
Recorded Future
Security Archives - TechRepublic
Security Archives - TechRepublic
阮一峰的网络日志
阮一峰的网络日志
T
Threatpost
P
Privacy International News Feed
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
MongoDB | Blog
MongoDB | Blog
I
Intezer
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Privacy & Cybersecurity Law Blog
A
Arctic Wolf
博客园 - 聂微东
博客园 - 叶小钗
Cisco Talos Blog
Cisco Talos Blog
H
Help Net Security
S
Schneier on Security
Y
Y Combinator Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
The Exploit Database - CXSecurity.com
T
Tor Project blog
月光博客
月光博客
NISL@THU
NISL@THU
A
About on SuperTechFans
Spread Privacy
Spread Privacy
Blog — PlanetScale
Blog — PlanetScale
D
DataBreaches.Net
雷峰网
雷峰网
C
CXSECURITY Database RSS Feed - CXSecurity.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 【当耐特】
G
Google Developers Blog
W
WeLiveSecurity
P
Palo Alto Networks Blog
The Last Watchdog
The Last Watchdog
K
Kaspersky official blog
博客园 - 司徒正美
L
LINUX DO - 热门话题
小众软件
小众软件

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派 万字剖析:千问App深度体验报告(2026) - 少数派 在2026年,如何真正防止别人抄袭你的作品 - 少数派 怎么用 50 块搭个 AI 语音助手?我踩了 3 天坑 - 少数派 YeeroAI:让 AI 对话真正成为知识管理的一部分 - 少数派 爬泰山 - 少数派 「旅图显影」 App 更新:这次,我们补上了一点「手感」 - 少数派 假期出门太折磨?我的 23 条经验帮你规划惬意旅行 - 少数派 工作流会变吗 - 少数派 Claude Opus 4.6 怎么用最省钱?我测了 5 种方案 - 少数派 GPT Image 2 让图文并茂不再稀罕 - 少数派 用户侧出发——什么是AI,我要不要学习? - 少数派 找片、转存、整理、播放一条龙!让你的付费网盘值回票价 - 少数派 欢迎试用!日课一问2.0插件 - 少数派 自己做的MDeditor,原本想购买 Typora 试了两次支付不成功,干脆自己做一个 - 少数派 vibe coding了一个 3MB 的小工具,让 ~/Downloads 彻底告别混乱 - 少数派 因为受不了 Mac 的风扇策略,我做了一个风扇控制工具 - 少数派 别只怪模型 - 少数派 Warp 终端的 AI 功能怎么用?我测了一周的体验 - 少数派 AI 写代码老是出 bug?这 5 个配置我后悔没早知道 - 少数派 「新玩意」苹果出相机可能就这样:Sigma BF + 45mm F2.8 DG Contemporary - 少数派 一个面向2030年的AI操作系统是什么样子的:浅谈cola这款有灵魂的Agent - 少数派 别只看写代码 - 少数派 每天解决10个问题,还是一口气攻坚解决400个? - 少数派 AI 交易机器人怎么搭?我用 Claude 跑了一周实盘 - 少数派 Maptoposter Online:把你爱的城市画成艺术海报 - 少数派 Function Calling 怎么用?我测了 3 个模型发现差距真大 - 少数派 Legend Talk:我做了个 AI 圆桌,让 160 位思想家围着你的问题转 - 少数派 如何找到自己的蓝方?在小县城寻找压力测试 - 少数派 语音输入与软件接口|2026年聊AI时,我们都聊些什么(上) - 少数派 混动已经卖爆,纯电又来补刀——钛7闪充版简直“不讲武德” - 少数派 本月玩什么|朋友收藏、识质存在、沙罗周期 - 少数派 为什么要每天坚持输出? - 少数派 Claude API 挂了好几个小时,你的项目有备用方案吗? - 少数派 Function Calling 没你想的复杂——我用它做了个有点用的工具 - 少数派 登录系统立即播放视频或者图片音乐的软件 - 少数派 我为什么创建 FlipHTML5 下载工具 - 少数派 残局没电?多品牌外设电量统一管理软件EasyBluetooth已支持RTSS游戏内显示以及AIDA64 - 少数派 前往通义路的路 - 少数派 太好看了,媲美Sun的个人导航页,NAS部署星云门户 - 少数派 乌黑嘴唇“一键检测”上线了 - 少数派 派早报:Claude AI 接入多个创意软件生态、FILCO 生产方接手品牌等 - 少数派 【更新】BearCLI、Claude 连接器与 MCP 服务器 - 少数派 记了上千条流水,还是看不懂财务?我做了一个让 AI 读懂账本的工作台 - 少数派 MINI R56 升级原厂 Sport 模式 - 少数派 新玩意 | 一棵柠檬树(仿真版) - 少数派 Momenta的“物理AI”野望,需迈过“含摩量”这道关 - 少数派 网页直接投屏控制手机!NAS一键部署PandaScrcpy,流畅丝滑可远程。 - 少数派 众测|邀你一同探索随身 AI 硬件入口 YoooClaw C·ONE - 少数派 2050大会:分享时间是真诚 参会记 - 少数派 iPad 赋能电影创作:国内首部宣纸手绘长片《燃比娃》的幕后故事 - 少数派 AI的审美:我用 8 个大模型给 100 张旅行照片打分 - 少数派 普通人如何破圈?去参加一个本地协会 - 少数派 把极空间的图标全换了,主题DIY全攻略打造你的专属NAS桌面 - 少数派 电子便签墙,帮你实现便签自由 - 少数派 我如何用三个 CLI 工具取代文档创建需求 - 少数派 原来真的有人可以玩一辈子 - 少数派 社区速递 139 | 派友热议三月买了啥、复古单反尼康 Df 体验 - 少数派 06 作品的赏析与评价 - 少数派 TDS REVIEW|索尼 WF-1000XM6 降噪真无线耳机体验 - 少数派 35.98万起售的第二代腾势D9,我看重的不是堆料,而是不凑合 - 少数派 鼠须管 Squirrel 皮肤配置指北 - 少数派 从watch ultra2换到redmi watch6 - 少数派 派早报:阿里巴巴发布视频生成模型 HappyHorse 1.0 等 - 少数派 别迷信1M - 少数派 家人们天塌了!网盘“大封杀”,多个渠道多条路,NAS部署PanHub - 少数派 AI与人勾心斗角!NAS一键部署AI狼人杀,假日休闲必备。 - 少数派 电商必备!Comfyui工作流批量生图插件,一次生成12张!支持Nano banana pro模型 - 少数派 Comfyui工作流配置Gpt-image-2模型教程,0.03/张 - 少数派 OpenClaw第三方APi怎么配置?可使用Gpt-image-2模型 - 少数派 会员社区话题精选 Ep. 103 - 少数派
PDF 复制中的文字重复问题 - 少数派
2018-12-21 · via 少数派

前两天,编辑 @⽂⼑漢三 在 Slack 上发给我一个 PDF 文件,问我知不知道为什么从里面复制出的中文会出现「重字」现象。他还提到,这个问题只在用系统自带的预览 app 打开时会出现,用其他 PDF 阅读器复制文字是正常的。

用预览 app 复制出的「结巴」文字
用预览 app 复制出的「结巴」文字

文刀拿这个问题来问我,恐怕是因为我之前写过一篇 解释 PDF 格式的文章,觉得我大概会知道答案。不过他其实高估了我的知识水平——我刚开始也不知道这是怎么回事。不过,经过一番搜索,我最终初步搞清楚了问题成因。因为这个问题涉及到一些很有意思的细节,这里把探索的过程写出来,供有类似疑问的朋友参考。


出现问题的 PDF 文档是由 一篇少数派文章 导出而得的。首先尝试复现问题:用预览 app 打开并随手复制一段,确实出现了很多重复的文字,看起来就像是「结巴」了一样,有一种莫名的喜感。换用 PDF Expert 打开再尝试复制,则没有这样的问题。

null

虽然不知道问题的具体成因,但根据经验,文字复制中的故障往往与编码有关,而 PDF 格式正是编码问题的大户。

我在之前的文章中提到,PDF 格式是「不识字」的。在显示文字时,阅读器只是机械地根据 PDF 语句的指令,将字体资源中特定码位的字形绘制在坐标指定的位置,而并不关心自己画出来的到底是什么字。只有在进行复制、搜索等操作时,PDF 才会根据内嵌的 CMap,将内部字体的编码和 Unicode 编码对应起来。因此,如果 CMap 缺失或损坏,就无法从 PDF 中正常复制文字,但并不影响文档的外观。

PDF 中文本编码的原理
PDF 中文本编码的原理

这次的问题会不会也跟 CMap 有关呢?这就要查看 PDF 的源码才能知道。不过,大多数 PDF 都经过压缩,用文本编辑器直接打开是不可读的。为此,我们首先用 qpdf 将其解压:

qpdf --stream-data=uncompress sspai.pdf sspai_unzip.pdf

这样,就可以用任意文本编辑器打开查看代码了。但即使如此,PDF 的源码结构也很混乱,从头翻看很难找到头绪。因此,我们可以从找准一个小处入手——例如标题中的这个「工」字。

查询 Unicode 字符表,可以知道「工」字的编码是 U+5DE5。既然 PDF 中有「工」字,那么源码中的某处一定会提到 5de5 这个编码。确实,简单搜索一下就可以找到这么一段:

1 beginbfchar
<0ae1><2f2f 5de5>
endbfchar

其中,beginbfcharendbfchar 正是 CMap 所用的语句。根据 PDF 语法,它表明 PDF 内嵌字体中编码为 0ae1 的字形,对应 Unicode 编码为 U+2F2FU+5DE5 的两个字符。

PDF 源码中提及的「工」字 Unicode 编码
PDF 源码中提及的「工」字 Unicode 编码

奇怪了,为什么是两个字符?

我们已经知道,U+5DE5 就是汉字「工」,那这个多出来的 U+2F2F 又是什么?再次 查询 Unicode 表,会发现 U+2F2F 竟然也是「工」。这两个字符是什么关系?它们是一回事吗?

答案是否定的。仔细看一下两个字符的 Unicode 信息:U+5DE5 的全名是「Ideograph labor, work; worker, laborer CJK」,位于 CJK Unified Ideographs(中日韩统一表意文字)区块。显然,这就是我们日常所用的汉字「工」。

另一方面, U+2F2F 的全名是「Kangxi Radical Work」,其所在区块是「Kangxi Radicals」(康熙字典部首)。换句话说,两个「工」虽然长得一模一样,但身份并不相同,一个是汉字,另一个是部首。

这样一来,我们也就知道预览 app 是怎么复制出「重复」的文字了。

实际上,它并没有复制出来两个一样的「工」字,而是同时复制出来了两个不同的字符——前一个是作为部首的「工」,后一个才是真正的汉字「工」。将预览的复制结果粘贴到 文本转 Unicode 编码工具 里,就能看得很明显:

看似重复的文字实际上是两个不同的字符
看似重复的文字实际上是两个不同的字符

不过,PDF 为什么要在 CMap 中作这样「一对多」的映射呢?的确,从预览 app 的角度看,它或许还有理由感到一点小委屈:我做错了什么,PDF 明明告诉我这是两个字啊?

回答这个问题,就要先了解「康熙字典部首」区块中的字符的用途。对此,这个网页 解释得很清楚(原文为繁体中文;粗体为笔者所加):

既然全部部首的字元都在另一个地方编了码,那么为何要再次编码呢?据统一码(即 Unicode——笔者注)的文件指出,本区块的字元只作部首之用,不应该当作一般文字用途,文件更进一步提出,必要时甚至可以用不同的字型格式,表明是属于本区块的字元。换句话说,例如编辑一本字典,部首页、部首标题和「参见某部若干画」等文字,都应使用本区块内的字元;而内文和字头、词条等文字部分,则应使用「中日韩统一表意文字区块」中的字元。这样做的原意,是希望让机器知道该字元现时所充当的角色:是「一般文字」,还是「部首文字」。当然,这些分别对人类来说可能没有作用,但对机器的语意分析是十分重要的。

实际上,类似的需求在使用拉丁字符的语言中同样存在。最典型的是西文排版中所谓 「合字」(ligature)的概念,即针对 fffi 这样笔画容易「打架」的字符组合,将其当作一个整体来专门设计造型。因此,这些字符组合在 Unicode 中需要有独立的码位,如 (U+FB00)、 (U+FB01) 等(请试着动手复制一下这些字符)。可是,合字在显示时是一个整体,而在复制和搜索时却要看作两个独立的字符。而在 PDF 中,合字的这种双重身份也正是通过 CMap 的「一对多」映射实现的。

合字
合字

因此,复制文字重复的故障,其责任并不在于 PDF 的编码。「一对多」的映射并不是一种冗余或者混淆,而是为了适应机器和用户的不同需要而必须加入的特殊处理。说到底,还是预览 App 的优化功夫没下到家,没有意识到 PDF 文本在显示、复制、搜索时应该受到不同的对待。这也再次应证了我之前文章中的一个观点:PDF 阅读器很多时候拼的不是功能有多丰富(反正都拼不过亲儿子 Acrobat),而是能不能做好复制、搜索这些基础功能的细节。


> 下载少数派 客户端、关注 少数派公众号 ,让你的工作更有效率 ⏱
> 特惠、好用的硬件产品,尽在 少数派 Pi Store 商店 🛒