C# 合并 RTF 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/628553/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 10:56:08  来源:igfitidea点击:

Merge RTF files

c#rtf

提问by PeteT

I have a set of RTF's stored in strings in C# is their a way to merge these into one document for printing as the user wants to print them as one document with the print settings appearing once. I can use office interop if necessary, obviously avoiding this is better.

我在 C# 中以字符串形式存储了一组 RTF,这是将它们合并到一个文档中进行打印的一种方法,因为用户希望将它们作为一个文档进行打印,并且打印设置出现一次。如有必要,我可以使用办公室互操作,显然避免这样做更好。

Edit: A page break would be necessary between each document I think I can just insert \page for this though

编辑:每个文档之间需要一个分页符,我想我可以为此插入 \page

采纳答案by anhldbk

Hereyou go (C# code's included in)

你(C# 代码包含在)

回答by MikeW

You would have to remove the trailing } from the first document.

您必须从第一个文档中删除尾随 }。

You would have to remove the {\rtf1... and {fonttbl.. and {colortbl... sections from the second document. Might need to look at any header, margins etc. that you might have.

您必须从第二个文档中删除 {\rtf1... 和 {fonttbl.. 和 {colortbl... 部分。可能需要查看您可能拥有的任何标题、边距等。

Separate them by a \page as you say.

正如你所说,用 \page 将它们分开。

This assumes the font and color tables are the same.

这假设字体和颜色表是相同的。

Probably better to get the print settings from the user then silently print each document separately, if that's an option.

如果这是一个选项,最好从用户那里获取打印设置然后单独打印每个文档。

Document 1:

文件1:

{\rtf1\ansi\ansicpg1252\deff0\deflang5129
{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}
{\colortbl;\red0\green0\blue0;}
\margl1134\margr1134\margt1134\margb1134\sectd 
\pard
Document One Content
\line
}

Document 2:

文件2:

{\rtf1\ansi\ansicpg1252\deff0\deflang5129
{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}
{\colortbl;\red0\green0\blue0;}
\margl1134\margr1134\margt1134\margb1134\sectd 
\pard
Document Two Content
\line
}

Merged Documents:

合并文件:

{\rtf1\ansi\ansicpg1252\deff0\deflang5129
{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}
{\colortbl;\red0\green0\blue0;}
\margl1134\margr1134\margt1134\margb1134\sectd 
\pard
Document One Content

\page

\pard

Document Two Content
\line
}

回答by Assaf Lavie

I guess there's also a way of doing this without getting into the details of the RTF format. Save your RTFs as files and use Automation of MS Word to open and append documents to each other (then save again as RTF).

我想还有一种方法可以做到这一点,而无需深入了解 RTF 格式的细节。将您的 RTF 保存为文件,并使用 MS Word 自动化来打开和附加文档(然后再次另存为 RTF)。

回答by Assaf Lavie

I've used this code two merge to rtf files, use de method Merge wiht de path of de files. If you have only de text you can modify it, but if you have bigger document you will be in a error of memory. I'm sorry for my english.

我已经使用这段代码两次合并到 rtf 文件,使用 de 方法合并 de 文件的路径。如果您只有 de 文本,您可以修改它,但如果您有更大的文档,则会出现内存错误。我很抱歉我的英语。

回答by Arjun Bandel

Just removing the font table will work only if both documents use the same set of fonts. You will need to uniquely merge (union) the font tables (font element wise) if you want to preserve font info of both the rtfs. This will work for n number of rtfs but again we need the union of individual font tables.. I am currently workin on developing the code for this union will post once ready.. :)

只有当两个文档都使用相同的字体集时,删除字体表才有效。如果您想保留两个 rtfs 的字体信息,您将需要唯一地合并(联合)字体表(字体元素明智)。这将适用于 n 个 rtfs,但我们再次需要单个字体表的联合.. 我目前正在开发此联合的代码,一旦准备就绪,将发布.. :)

In our project we also used the Office Doc object to render rtfs and benefit from word's automation. But it creates a dependency of having ms-word installed. Particularly it can raise problem if the code needs to run from a server where memory is also a concern as using word API causes instance of ms-word to be loaded in memory. But the solution does work!!

在我们的项目中,我们还使用了 Office Doc 对象来呈现 rtfs 并受益于 word 的自动化。但它创建了安装 ms-word 的依赖项。特别是如果代码需要从内存也是一个问题的服务器运行,它会引发问题,因为使用 word API 会导致 ms-word 的实例加载到内存中。但解决方案确实有效!!

Okay!! So ready with the code for union of Font tables in two rtfs and merging them to preserve varying fonts..Please read the RTFs in strings.

好的!!准备好在两个 rtfs 中合并字体表的代码并将它们合并以保留不同的字体..请阅读字符串中的 RTF。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
//Arjun 02nd May
namespace MergeRtf
{
class RTFUtils
{
    public static string getRTFBlock(string blockName,string rtf){

       int i=rtf.IndexOf(@"{\"+blockName);
        int startOfBlock = i;
        //Next find the end of style sheet element tag
        Stack<char> braceHolder=new Stack<char>();
        braceHolder.Push('{');

        string stylesheetBlock = "";

        while (braceHolder.Count != 0&&i<rtf.Length) {
            i++;
            if (rtf[i] == '{') {
                braceHolder.Push('{');
                continue;
            }
            if (rtf[i] == '}') {
                braceHolder.Pop();
            }
        }
        if (braceHolder.Count == 0) { 
        //encountered the ending tag for stylesheet
            stylesheetBlock = rtf.Substring(startOfBlock, i-startOfBlock+1); 
            return stylesheetBlock;
        }
        else
        {
            //Error in doc format
            throw (new Exception("Error in doc format"));
        }


    }



    public static string MergeRTFs(string rtf1,string rtf2,string mergingBreak){ 
        //mergingBreak is the type of break that will be sandwiched between the docs
        //get the fonttbl blocks for both the documents
        string fontTableOfDoc1 = getRTFBlock("fonttbl", rtf1);
        string fontTableOfDoc2 = getRTFBlock("fonttbl", rtf2);

        //get font lists
        List<string> fontList1 = ExtractRTFFonts(fontTableOfDoc1);
        List<string> fontList2 = ExtractRTFFonts(fontTableOfDoc2);

        //Union the font list
        IEnumerable<string> mergedfonts = fontList1.Union(fontList2);
        List<string> fontList3 = new List<string>(mergedfonts);
        string mergedFontListBlock = @"{\fonttbl";
        foreach (string font in fontList3) {
            mergedFontListBlock += font;
        }
        mergedFontListBlock += "}";

        //Find location of the fonttable in doc 1 and doc 2
        int indexOfFontTable1 = rtf1.IndexOf(@"{\fonttbl");
        int indexOfFontTable2 = rtf2.IndexOf(@"{\fonttbl");

        string rtfMerged = "";
        //Get rtf content before and after fonttable
        string headerRTF1 = rtf1.Substring(0, indexOfFontTable1);
        int endOfFontTableIndex=indexOfFontTable1 + (fontTableOfDoc1.Length-1);
        string trailerRTF1 = rtf1.Substring(endOfFontTableIndex + 1,      rtf1.LastIndexOf('}') - (endOfFontTableIndex + 1)); //-2 to remove ending } of 1st doc
        //create the first rtf with merged fontlist
        rtfMerged = headerRTF1 + mergedFontListBlock + trailerRTF1;
        //next identify trailer part after font table in rtf 2
        string trailerRTF2 = rtf2.Substring(indexOfFontTable2 + fontTableOfDoc2.Length);
        rtfMerged += mergingBreak + trailerRTF2;

        return rtfMerged;
    }

    private static List<string> ExtractRTFFonts(string fontTableBlock) {
        Stack<char> braces = new Stack<char>();
        List<string> fonts = new List<string>();
        int fontDefStart=0,fontDefLength;
        braces.Push('{');
        int i=0;
        while (braces.Count > 0 && i < fontTableBlock.Length) { 
            i++;
            if (fontTableBlock[i] == '{') {
                braces.Push('{');
                if (braces.Count == 2) { 
                //means font definition brace started store the position
                    fontDefStart = i;
                }
                continue;
            }
            if (fontTableBlock[i] == '}') {
                braces.Pop();
                if (braces.Count == 1) { 
                //means only root level brace left identifying one font definition ended
                    fontDefLength = i - fontDefStart + 1;
                    fonts.Add(fontTableBlock.Substring(fontDefStart,fontDefLength));
                }
            }
        }

        if (braces.Count == 0)
        {
            //everything is fine then
            return fonts;
        }
        else { 
        //malformed font table passed
            throw (new Exception("Malformed font table passed"));
        }
    }


}
} 

回答by Jerry

You can use two rich text boxes. Read the rtf file into one rich text box (rtbTemp), and then cut and paste the text into the other (rtbMerged). For example:

您可以使用两个富文本框。将 rtf 文件读入一个富文本框 (rtbTemp),然后将文本剪切并粘贴到另一个 (rtbMerged) 中。例如:

RichTextBox rtbTemp = new RichTextBox();
RichTextBox rtbMerged = new RichTextBox();

string Merge(string s1, string s2)
{
    rtbTemp.Rtf = s1;
    rtbTemp.SelectAll();
    rtbTemp.Cut();
    rtbMerged.Paste();

    rtbMerged.AppendText(Environment.NewLine);
    rtbMerged.AppendText(Environment.NewLine);

    rtbTemp.Rtf = s2;
    rtbTemp.SelectAll();
    rtbTemp.Cut();
    rtbMerged.Paste();

    return rtbMerged.Rtf;
}

回答by yeye

I only remove 3 charecter from end of first rtf file, and one of first char of second rtf file and it work good!

我只从第一个 rtf 文件的末尾和第二个 rtf 文件的第一个字符中删除了 3 个字符,它运行良好!

RichTextBox r = new RichTextBox();
r.Rtf = rtf1.Rtf.Substring(0, rtf1.Rtf.Length - 3) + rtf2.Rtf.Substring(1,rtf2.Rtf.Length - 1)