You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C#逐页读取RTF文档并提取带对应页码的指定内容

嘿,我帮你搞定这个RTF逐页提取关键词和页码的问题!之前用RichTextBox只能拿到全量文本确实头疼,因为RTF本身并没有原生存储页码信息——页码是渲染时根据排版计算出来的。不过我们可以借助WinForms的打印机制来绕开这个问题,具体思路和代码如下:

核心思路

利用Windows Forms的PrintDocument控件结合RichTextBox的打印能力:当触发打印流程时,PrintDocument会逐页触发PrintPage事件,我们可以在这个事件里获取当前页的文本内容,同时记录对应的页码,最后在每页文本中搜索目标关键词并建立映射。

具体实现步骤
  1. 在VS2015的WinForms项目中,添加RichTextBox、PrintDocument和PrintPreviewDialog控件(也可以通过代码动态创建)。
  2. 将RTF文件加载到RichTextBox中。
  3. 绑定PrintDocument的PrintPage事件,在事件处理逻辑中提取当前页文本、搜索关键词并记录页码。
  4. 通过PrintPreviewDialog触发打印流程(不需要实际打印,只是用来触发分页事件)。
完整代码示例

首先在Form类中声明必要的变量:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace RTFFilePageReader
{
    public partial class MainForm : Form
    {
        // 存储关键词和对应页码的映射
        private Dictionary<string, List<int>> _keywordPageMap = new Dictionary<string, List<int>>();
        // 当前页码计数器
        private int _currentPage = 0;
        // 你要搜索的目标关键词列表
        private List<string> _targetKeywords = new List<string> { "特定词语1", "特定词语2" };

        public MainForm()
        {
            InitializeComponent();
        }

然后添加加载RTF和触发分页处理的方法:

private void btnProcess_Click(object sender, EventArgs e)
        {
            // 重置状态
            _keywordPageMap.Clear();
            _currentPage = 0;

            // 加载RTF文件到RichTextBox
            try
            {
                richTextBox1.LoadFile("你的RTF文件路径.rtf", RichTextBoxStreamType.RichText);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载文件失败: {ex.Message}");
                return;
            }

            // 配置PrintDocument
            printDocument1.DefaultPageSettings.Margins = new System.Drawing.Printing.Margins(50, 50, 50, 50);
            printDocument1.PrintPage += PrintDocument1_PrintPage;

            // 用PrintPreviewDialog触发分页事件(最小化窗口避免干扰)
            using (PrintPreviewDialog previewDialog = new PrintPreviewDialog())
            {
                previewDialog.Document = printDocument1;
                previewDialog.WindowState = FormWindowState.Minimized;
                previewDialog.ShowDialog();
            }

            // 输出结果到控制台或者界面
            ShowKeywordResults();
        }

接下来是核心的PrintPage事件处理逻辑:

private void PrintDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            _currentPage++;

            // 获取当前页文本的起始和结束索引
            int startCharIndex = richTextBox1.GetCharIndexFromPosition(new Point(0, e.MarginBounds.Top));
            int endCharIndex = richTextBox1.GetCharIndexFromPosition(new Point(0, e.MarginBounds.Bottom));

            // 处理最后一页的边界情况
            if (endCharIndex > richTextBox1.Text.Length - 1)
                endCharIndex = richTextBox1.Text.Length - 1;

            // 提取当前页的文本
            string currentPageText = richTextBox1.Text.Substring(startCharIndex, endCharIndex - startCharIndex + 1);

            // 在当前页文本中搜索目标关键词
            foreach (string keyword in _targetKeywords)
            {
                int keywordIndex = currentPageText.IndexOf(keyword, StringComparison.OrdinalIgnoreCase);
                while (keywordIndex != -1)
                {
                    // 如果关键词不在映射中,初始化列表
                    if (!_keywordPageMap.ContainsKey(keyword))
                        _keywordPageMap[keyword] = new List<int>();
                    // 避免重复记录同一页码
                    if (!_keywordPageMap[keyword].Contains(_currentPage))
                        _keywordPageMap[keyword].Add(_currentPage);

                    // 继续搜索下一个匹配项
                    keywordIndex = currentPageText.IndexOf(keyword, keywordIndex + keyword.Length, StringComparison.OrdinalIgnoreCase);
                }
            }

            // 告诉PrintDocument是否还有下一页
            e.HasMorePages = endCharIndex < richTextBox1.Text.Length - 1;
        }

最后添加结果展示的方法:

private void ShowKeywordResults()
        {
            string result = "";
            foreach (var kvp in _keywordPageMap)
            {
                result += $"关键词: *{kvp.Key}*,出现页码: {string.Join(", ", kvp.Value)}\n";
            }
            MessageBox.Show(result, "关键词搜索结果");
            // 也可以输出到控制台
            Console.WriteLine(result);
        }
    }
}
注意事项
  • 分页一致性:PrintDocument的页面设置(纸张大小、边距)会直接影响分页结果,要确保和你实际文档的排版设置一致,否则页码可能不准确。
  • 复杂格式处理:如果RTF包含表格、图片等复杂元素,可能需要调整GetCharIndexFromPosition的坐标计算,确保能准确获取每页的文本范围。
  • 性能优化:如果是超大文档,可以考虑异步处理,避免UI卡顿。

内容的提问来源于stack exchange,提问作者Anish Sivadas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:19:42