C++无法直接提取PDF文本,因PDF是含对象流、压缩和指令的二进制格式,非纯文本;需用libpoppler或pdfium等第三方库解析。

C++ 本身没有内置 PDF 文本提取能力,必须依赖第三方库;直接用标准库或系统 API 读取 PDF 文件只会得到二进制乱码或压缩流,无法解析出可读文本。
为什么不能用 fstream 或 std::ifstream 直接读文本?
PDF 不是纯文本格式,而是包含对象流、交叉引用表、压缩(如 FlateDecode)、字体映射、内容流指令(如 Tj、TJ)的二进制/混合格式。即使文件以 ASCII 开头(如 %PDF-1.7),后续内容仍是结构化数据,不是 UTF-8 或 GBK 编码的自然语言文本。
常见错误现象:
- 用
std::ifstream以std::ios::binary模式读取后std::string转换为const char*,再传给printf或std::cout—— 输出大量不可见字符、乱码或程序崩溃 - 跳过头部直接搜索
/Font或BT ... ET段落 —— 忽略对象间接引用、流解压、CID 字符映射,提取结果为空或错字(如“你好”变成“ä½ å¥½”)
推荐方案:用 libpoppler(Linux/macOS)或 pdfium(跨平台、Google 维护)
libpoppler 接口简洁,C++ 封装成熟;pdfium 更底层但支持更多 PDF 特性(如表单、注释),且无 GPL 传染风险(BSD 许可)。Windows 下建议优先试 pdfium,避免 poppler 的 MinGW 兼容问题。
立即学习“C++免费学习笔记(深入)”;
实操建议:
- Linux:用包管理器安装开发包,例如
sudo apt install libpoppler-cpp-dev,链接-lpoppler-cpp - macOS:
brew install poppler,头文件路径通常为/opt/homebrew/include/poppler/cpp/ - Windows:从 pdfium-binaries 下载预编译库,注意匹配架构(x64/Win32)和运行时(MD/MT)
- 关键初始化步骤:调用
FPDF_InitLibrary()(pdfium)或构造poppler::document::load_from_file()(poppler),失败时检查文件路径是否含中文、权限是否受限
最简可用代码片段(以 pdfium 为例)
以下代码仅提取第一页文本,不处理多页、图片内 OCR、加密 PDF(需额外密码参数):
#include <fpdfview.h>
#include <iostream>
#include <string>
int main() {
FPDF_LIBRARY_CONFIG config = {};
config.version = 2;
config.m_pUserFontPaths = nullptr;
config.m_pIsolate = nullptr;
config.m_v8EmbedderSlot = 0;
FPDF_InitLibraryWithConfig(&config);
FPDF_DOCUMENT doc = FPDF_LoadDocument("test.pdf", nullptr);
if (!doc) {
std::cerr << "Failed to load PDF: " << FPDF_GetLastError() << "\n";
return -1;
}
FPDF_PAGE page = FPDF_LoadPage(doc, 0);
FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
int len = FPDFText_CountChars(text_page);
for (int i = 0; i < len; ++i) {
unsigned short ch = FPDFText_GetUnicode(text_page, i);
std::cout << static_cast<char>(ch > 127 ? '?' : ch); // 简单 ASCII 映射,实际应转 UTF-8
}
std::cout << "\n";
FPDFText_ClosePage(text_page);
FPDF_ClosePage(page);
FPDF_CloseDocument(doc);
FPDF_DestroyLibrary();
}
注意点:
-
FPDFText_GetUnicode()返回的是 UTF-16 码位,不是字节流;直接强转char会丢高位,生产环境必须用std::codecvt_utf8<char16_t></char16_t>或iconv转 UTF-8 - 未处理 PDF 加密:若
FPDF_LoadDocument返回nullptr且FPDF_GetLastError()是FPDF_ERR_PASSWORD,需调用FPDF_UnloadCustomAccess()+ 密码回调 - 未释放内存或未调用
FPDF_DestroyLibrary()会导致 Windows 下 DLL 卸载失败、进程退出卡住
真正麻烦的从来不是“怎么写第一行代码”,而是字体嵌入缺失时的 Unicode 映射失败、CJK 字符的 CID 到 Unicode 表查找缺失、以及扫描型 PDF(本质是图片)完全无法提取——这时候你得切到 OCR 工具,比如 tesseract 配合 pdf2image,那又是另一个链路了。



















