一个用于读取常见文档格式的 Go 语言库,支持 Office 文档、PDF、文本文件等多种格式。
- ✅ 读取 DOCX (Word 文档) 的文本内容和元数据
- ✅ 读取 XLSX (Excel 表格) 的文本内容和结构化数据
- ✅ 读取 PPTX (PowerPoint 演示文稿) 的文本内容
- ✅ 读取 PDF 文件的文本内容和元数据
- ✅ 读取 TXT 纯文本文件
- ✅ 读取 CSV 表格文件(支持结构化数据)
- ✅ 读取 Markdown (.md) 文件
- ✅ 读取 RTF 富文本格式(基础文本提取)
- ✅ 统一的接口设计,自动识别文件格式
- ✅ 提取文档元数据(标题、作者、创建时间等)
- ✅ 支持中文内容
go get github.com/wsshow/docreaderpackage main
import (
"fmt""log""github.com/wsshow/docreader"
)
funcmain() {
// 自动识别文件格式并读取doc, err:=docreader.ReadDocument("example.docx")
iferr!=nil {
log.Fatal(err)
}
fmt.Printf("文件: %s\n", doc.FilePath)
fmt.Printf("内容: %s\n", doc.Content)
fmt.Printf("元数据: %v\n", doc.Metadata)
}// 方式 1: 使用统一接口doc, err:=docreader.ReadDocument("document.docx")
iferr!=nil {
log.Fatal(err)
}
fmt.Println(doc.Content)
// 方式 2: 使用专用读取器reader:=&docreader.DocxReader{}
content, err:=reader.ReadText("document.docx")
iferr!=nil {
log.Fatal(err)
}
fmt.Println(content)
// 获取元数据metadata, err:=reader.GetMetadata("document.docx")
fmt.Printf("标题: %s\n", metadata["title"])
fmt.Printf("作者: %s\n", metadata["creator"])// 读取 PDF 内容doc, err:=docreader.ReadDocument("document.pdf")
iferr!=nil {
log.Fatal(err)
}
fmt.Println(doc.Content)
// 获取 PDF 元数据reader:=&docreader.PdfReader{}
metadata, err:=reader.GetMetadata("document.pdf")
fmt.Printf("页数: %s\n", metadata["pages"])
fmt.Printf("作者: %s\n", metadata["author"])// 基本读取doc, err:=docreader.ReadDocument("spreadsheet.xlsx")
iferr!=nil {
log.Fatal(err)
}
fmt.Println(doc.Content)
// 高级用法 - 获取结构化数据reader:=&docreader.XlsxReader{}
// 获取指定工作表的数据rows, err:=reader.GetSheetData("spreadsheet.xlsx", "Sheet1")
iferr!=nil {
log.Fatal(err)
}
for_, row:=rangerows {
fmt.Println(row) // []string
}
// 获取所有工作表的数据allSheets, err:=reader.GetAllSheetsData("spreadsheet.xlsx")
forsheetName, rows:=rangeallSheets {
fmt.Printf("工作表: %s\n", sheetName)
for_, row:=rangerows {
fmt.Println(row)
}
}// 基本读取doc, err:=docreader.ReadDocument("presentation.pptx")
iferr!=nil {
log.Fatal(err)
}
fmt.Println(doc.Content)
// 高级用法 - 按幻灯片分组reader:=&docreader.PptxReader{}
slides, err:=reader.GetSlides("presentation.pptx")
iferr!=nil {
log.Fatal(err)
}
fori, slide:=rangeslides {
fmt.Printf("=== 幻灯片 %d ===\n", i+1)
fmt.Println(slide)
}
// 获取元数据metadata, err:=reader.GetMetadata("presentation.pptx")
fmt.Printf("幻灯片总数: %s\n", metadata["slide_count"])// 读取文本文件doc, err:=docreader.ReadDocument("document.txt")
iferr!=nil {
log.Fatal(err)
}
fmt.Println(doc.Content)// 基本读取doc, err:=docreader.ReadDocument("data.csv")
iferr!=nil {
log.Fatal(err)
}
fmt.Println(doc.Content)
// 高级用法 - 获取结构化数据reader:=&docreader.CsvReader{}
records, err:=reader.GetRecords("data.csv")
iferr!=nil {
log.Fatal(err)
}
for_, row:=rangerecords {
fmt.Println(row) // []string
}// 读取 Markdown 文件doc, err:=docreader.ReadDocument("README.md")
iferr!=nil {
log.Fatal(err)
}
fmt.Println(doc.Content)// 读取 RTF 文件(基础文本提取)doc, err:=docreader.ReadDocument("document.rtf")
iferr!=nil {
log.Fatal(err)
}
fmt.Println(doc.Content)DocReader 提供了强大的配置系统,允许你精确控制要读取的页面和行。
// 示例 1: 读取指定页码config:=docreader.NewReadConfig().
WithPages(0, 2, 4) // 读取第 0、2、4 页result, err:=docreader.ReadDocumentWithConfig("document.pdf", config)
// 示例 2: 读取页码范围config:=docreader.NewReadConfig().
WithPageRange(0, 5) // 读取第 0-5 页// 示例 3: 读取指定行config:=docreader.NewReadConfig().
WithLines(0, 5, 10) // 每页只读取第 0、5、10 行// 示例 4: 读取行范围config:=docreader.NewReadConfig().
WithLineRange(5, 15) // 每页只读取第 5-15 行// 示例 5: 组合多个范围config:=docreader.NewReadConfig().
WithPageRange(0, 2).
WithPageRange(5, 7). // 读取第 0-2 页和第 5-7 页WithLineRange(0, 10) // 每页读取第 0-10 行// 为特定页面配置不同的行config:=docreader.NewReadConfig().
AddPageLines(0, 1, 3, 5). // 第 0 页:读取第 1、3、5 行AddPageLineRange(1, 0, 10). // 第 1 页:读取第 0-10 行AddPageConfig(2, []int{2, 4}, [][2]int{{6, 8}}) // 第 2 页:读取第 2、4 行和第 6-8 行result, err:=docreader.ReadDocumentWithConfig("document.pdf", config)// 只读取指定的工作表config:=docreader.NewReadConfig().
WithSheetNames("Sheet1", "Summary")
result, err:=docreader.ReadDocumentWithConfig("spreadsheet.xlsx", config)result, err:=docreader.ReadDocumentWithConfig("document.pdf", config)
iferr!=nil {
log.Fatal(err)
}
// 访问结构化数据fmt.Printf("总页数: %d\n", result.TotalPages)
fmt.Printf("总行数: %d\n", result.TotalLines)
// 遍历每一页for_, page:=rangeresult.Pages {
fmt.Printf("页码: %d, 行数: %d\n", page.PageNumber, page.TotalLines)
fori, line:=rangepage.Lines {
fmt.Printf(" 行 %d: %s\n", i, line)
}
}
// 获取完整内容fmt.Println(result.Content)DocReader 提供了智能的文本清理功能,可以优化提取的文本内容,特别适合用于大模型处理。
// 使用默认清理(推荐)doc, err:=docreader.ReadDocumentWithClean("document.pdf")
// 效果:移除行首尾空格、压缩多余空格、移除控制字符、最多保留1个连续空行// 最小清理(保留格式)doc, err:=docreader.ReadDocument("document.txt")
doc.CleanContentMinimal()
// 效果:仅移除行首尾空格、压缩多余空格、移除控制字符,保留所有空行// 激进清理(最大压缩)doc, err:=docreader.ReadDocument("document.docx")
doc.CleanContentAggressive()
// 效果:移除所有空行,压缩空格,移除控制字符// 创建自定义清理器cleaner:=&docreader.TextCleaner{
TrimSpaces: true, // 移除行首行尾空格RemoveExtraSpaces: true, // 压缩连续空格为一个RemoveControlChars: true, // 移除控制字符MaxBlankLines: 2, // 最多保留 2 个连续空行(-1=不限制,0=移除所有)
}
// 在读取时应用清理doc, err:=docreader.ReadDocumentWithCleanConfig("document.pdf", cleaner)
// 或者对已读取的文档应用清理doc, err:=docreader.ReadDocument("document.txt")
doc.CleanContentWith(cleaner)typeTextCleanerstruct {
// TrimSpaces: 是否移除行首行尾空格TrimSpacesbool// RemoveExtraSpaces: 是否将连续空格压缩为一个RemoveExtraSpacesbool// RemoveControlChars: 是否移除特殊控制字符(保留换行符和制表符)RemoveControlCharsbool// MaxBlankLines: 最大连续空行数// -1: 不限制,保留所有空行// 0: 移除所有空行// 1: 最多保留 1 个连续空行(压缩多余空行)// N: 最多保留 N 个连续空行MaxBlankLinesint
}自动识别文件格式并读取内容,返回包含内容和元数据的 Document 对象。
读取文档并自动应用默认文本清理。
读取文档并应用自定义文本清理配置。
根据配置精确读取文档,返回结构化的结果。
创建一个新的读取配置对象,支持链式调用。
所有读取器都实现此接口:
ReadText(filePath string) (string, error)- 读取文本内容GetMetadata(filePath string) (map[string]string, error)- 获取元数据
支持高级配置的读取器接口(所有读取器都实现):
ReadWithConfig(filePath string, config *ReadConfig) (*DocumentResult, error)- 根据配置读取文档
// 页面选择config.WithPages(pages...int) // 设置要读取的离散页码config.WithPageRange(start, endint) // 添加页码范围// 全局行选择(应用到所有页)config.WithLines(lines...int) // 设置要读取的离散行号config.WithLineRange(start, endint) // 添加行号范围// 页面级行配置(覆盖全局配置)config.AddPageLines(pageIndexint, lines...int) // 为指定页添加离散行config.AddPageLineRange(pageIndex, start, endint) // 为指定页添加行范围config.AddPageConfig(pageIndexint, lineIndexes []int, lineRanges [][2]int) // 为指定页添加完整配置// XLSX 特有
config.WithSheetNames(names...string) // 设置要读取的工作表名称// Selector 统一的选择器,用于选择页码或行号typeSelectorstruct {
Indexes []int// 离散索引:[0, 2, 5]Ranges [][2]int// 连续范围:[[0,2], [5,10]]
}
// ReadConfig 读取配置typeReadConfigstruct {
PageSelectorSelector// 页面选择器LineSelectorSelector// 全局行选择器PageConfigs []PageConfig// 页面级配置(优先级高于全局)SheetNames []string// XLSX 工作表名称
}
// DocumentResult 结构化的文档读取结果typeDocumentResultstruct {
FilePathstringPages []PageContent// 结构化页面内容TotalPagesintTotalLinesintMetadatamap[string]stringContentstring// 完整文本内容
}
// PageContent 单页内容typePageContentstruct {
PageNumberintPageNamestring// 工作表名称(XLSX)Lines []stringTotalLinesint
}ReadText()- 读取段落和表格文本GetMetadata()- 获取标题、作者、创建/修改时间等
ReadText()- 逐页读取文本内容GetMetadata()- 获取页数、作者、创建时间等
ReadText()- 读取所有工作表的文本GetMetadata()- 获取工作表列表、文档属性等GetSheetData(filePath, sheetName string)- 获取指定工作表的结构化数据GetAllSheetsData(filePath string)- 获取所有工作表的结构化数据
ReadText()- 读取所有幻灯片的文本GetMetadata()- 获取幻灯片数量、标题等GetSlides(filePath string)- 按幻灯片分组获取文本
ReadText()- 读取纯文本内容GetMetadata()- 获取文件大小、修改时间等
ReadText()- 读取 CSV 文件的格式化文本GetMetadata()- 获取行数、列数、文件信息等GetRecords(filePath string)- 获取结构化的 CSV 数据
ReadText()- 读取 Markdown 原始内容GetMetadata()- 获取文件大小、修改时间等
ReadText()- 提取 RTF 文件的纯文本内容GetMetadata()- 获取文件大小、修改时间等
- title - 标题
- subject - 主题
- creator - 创建者
- description - 描述
- created - 创建时间
- modified - 修改时间
- title - 标题
- author - 作者
- subject - 主题
- creator - 创建程序
- producer - 生成程序
- creation_date - 创建日期
- modification_date - 修改日期
- pages - 页数
- title - 标题
- subject - 主题
- creator - 创建者
- sheets - 工作表列表
- sheet_count - 工作表数量
- active_sheet - 活动工作表
当前 PDF 读取器使用 ledongthuc/pdf 库,该库对某些 PDF 文件中的中文字符(CJK 字体)支持有限。如果 PDF 文件使用了嵌入式中文字体或特殊编码,可能会出现乱码。
建议:
- 对于包含大量中文内容的 PDF,建议使用其他专业 PDF 处理工具
- 英文和数字内容可以正常提取
- 元数据提取不受影响
库提供了统一的错误封装和类型检查功能,方便进行精确的错误处理。
var (
ErrUnsupportedFormat=errors.New("unsupported file format") // 不支持的文件格式ErrFileNotFound=errors.New("file not found") // 文件不存在ErrFileOpen=errors.New("failed to open file") // 无法打开文件ErrFileRead=errors.New("failed to read file") // 读取文件失败ErrFileParse=errors.New("failed to parse file") // 解析文件失败ErrInvalidFormat=errors.New("invalid file format") // 文件格式无效ErrEmptyFile=errors.New("file is empty") // 文件为空ErrSheetNotFound=errors.New("sheet not found") // 工作表不存在
)doc, err:=docreader.ReadDocument("file.docx")
iferr!=nil {
log.Printf("读取文件失败: %v", err)
return
}doc, err:=docreader.ReadDocument("file.unknown")
iferr!=nil {
// 使用 errors.Is 进行错误类型判断iferrors.Is(err, docreader.ErrUnsupportedFormat) {
log.Println("不支持的文件格式")
} elseiferrors.Is(err, docreader.ErrFileNotFound) {
log.Println("文件不存在")
} elseiferrors.Is(err, docreader.ErrFileOpen) {
log.Println("无法打开文件")
} else {
log.Printf("其他错误: %v", err)
}
return
}doc, err:=docreader.ReadDocument("file.pdf")
iferr!=nil {
// 使用辅助函数进行错误检查ifdocreader.IsUnsupportedFormat(err) {
log.Println("不支持的文件格式")
} elseifdocreader.IsFileNotFound(err) {
log.Println("文件不存在")
} elseifdocreader.IsFileOpen(err) {
log.Println("无法打开文件")
} elseifdocreader.IsFileRead(err) {
log.Println("读取文件失败")
} elseifdocreader.IsFileParse(err) {
log.Println("解析文件失败")
} else {
log.Printf("未知错误: %v", err)
}
return
}doc, err:=docreader.ReadDocument("file.docx")
iferr!=nil {
// 错误信息包含操作名称和文件路径// 格式: "操作名称: 文件路径: 错误详情"log.Printf("详细错误: %v", err)
// 使用 errors.Unwrap 获取原始错误ifunwrapped:=errors.Unwrap(err); unwrapped!=nil {
log.Printf("原始错误: %v", unwrapped)
}
return
}package main
import (
"errors""log""github.com/wsshow/docreader"
)
funcmain() {
filePath:="document.pdf"doc, err:=docreader.ReadDocument(filePath)
iferr!=nil {
handleError(err)
return
}
log.Printf("成功读取文档,内容长度: %d", len(doc.Content))
}
funchandleError(errerror) {
switch {
casedocreader.IsUnsupportedFormat(err):
log.Println("错误: 不支持的文件格式,请使用 .docx, .pdf, .xlsx, .pptx, .txt, .csv, .md 或 .rtf 格式")
casedocreader.IsFileNotFound(err):
log.Println("错误: 文件不存在,请检查文件路径")
casedocreader.IsFileOpen(err):
log.Println("错误: 无法打开文件,请检查文件权限")
casedocreader.IsFileRead(err):
log.Println("错误: 读取文件失败,文件可能已损坏")
casedocreader.IsFileParse(err):
log.Println("错误: 解析文件失败,文件格式可能不正确")
default:
log.Printf("错误: %v", err)
}
}