科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件使用 C# 编程对 RTF 文档进行操作

使用 C# 编程对 RTF 文档进行操作

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

笔者正在用C#开发一个名为XWriter的文本编辑器(点击下载),其中需要提供对RTF文档的支持,以前从没有搞过RTF文档,因此临……

作者:袁永福 来源:博客园 2007年11月19日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
首先是做一个RTF文档书写器,虽然生成RTF文档的操作可以看作拼凑RTF字符串,但在编程实践中不能真的这么拼凑,得仿造System.Xml.XmlWriter来做一个RTF文档书写器,我编了个名为RTFWriter的RTF文档书写器,该书写器内部实现了基础的RTF文档格式的控制,能保证输出正确的RTF文档,它还提供了比较方便的编程接口,便于其他程序模块调用。这个RTF文档书写器完整的C#代码如下:

以下是引用片段:
  /// 
  /// RTF文档书写器
  /// 
  /// 
  /// 本书写器对生成RTF文档提供了基础的支持
  /// 编制 袁永福 http://www.xdesigner.cn
  /// 
  public class RTFWriter : System.IDisposable
  {
  #region 测试代码 ******************************************************
  [System.STAThread]
  static void Main()
  {
  TestWriteFile();
  TestClipboard();
  }
  /// 
  /// 测试生成RTF文件
  /// 执行这个函数后可以使用 MS Word 打开文件 c:\a.rtf
  /// 
  internal static void TestWriteFile( )
  {
  RTFWriter w = new RTFWriter( "c:\\a.rtf" ) ;
  TestBuildRTF( w );
  w.Close();
  System.Windows.Forms.MessageBox.Show("好了,你可以打开文件 c:\\a.rtf 了.");
  }
  /// 
  /// 测试生成RTF文档并设置到系统剪切板中
  /// 执行这个函数后就可以在 MS Word中使用粘贴操作来显示程序生成的文档了
  /// 
  internal static void TestClipboard()
  {
  System.IO.StringWriter myStr = new System.IO.StringWriter();
  RTFWriter w = new RTFWriter( myStr );
  TestBuildRTF( w );
  w.Close();
  System.Windows.Forms.DataObject data = new System.Windows.Forms.DataObject();
  data.SetData( System.Windows.Forms.DataFormats.Rtf , myStr.ToString());
  System.Windows.Forms.Clipboard.SetDataObject( data , true );
  System.Windows.Forms.MessageBox.Show("好了,你可以在MS Word 中粘贴文本了.");
  }
  /// 
  /// 测试生成RTF文档
  /// 
  /// RTF文档书写器
  private static void TestBuildRTF( RTFWriter w )
  {
  w.Encoding = System.Text.Encoding.GetEncoding( 936 );
  // 输出文件头
  w.WriteStartGroup();
  w.WriteKeyword("rtf1");
  w.WriteKeyword("ansi");
  w.WriteKeyword("ansicpg" + w.Encoding.CodePage );
  // 输出字体表
  w.WriteStartGroup();
  w.WriteKeyword("fonttbl");
  w.WriteStartGroup();
  w.WriteKeyword("f0");
  w.WriteText("隶书;");
  w.WriteEndGroup();
  w.WriteStartGroup();
  w.WriteKeyword("f1");
  w.WriteText("宋体;");
  w.WriteEndGroup();
  w.WriteEndGroup();
  // 输出颜色表
  w.WriteStartGroup();
  w.WriteKeyword("colortbl");
  w.WriteText(";");
  w.WriteKeyword("red0");
  w.WriteKeyword("green0");
  w.WriteKeyword("blue255");
  w.WriteText(";");
  w.WriteEndGroup();
  // 输出正文
  w.WriteKeyword("qc"); // 设置居中对齐
  w.WriteKeyword("f0"); // 设置字体
  w.WriteKeyword("fs30"); // 字体大小
  w.WriteText("这是第一段文本 ");
  w.WriteKeyword("cf1"); // 设置颜色
  w.WriteText("隶书 ");
  w.WriteKeyword("cf0"); // 设置为默认颜色
  w.WriteKeyword("f1"); // 设置字体
  w.WriteText("居中对齐 ABC12345");
  w.WriteKeyword("par"); // 开始新的段落
  w.WriteKeyword("pard"); // 清除居中对齐
  w.WriteKeyword("f1"); // 设置字体
  w.WriteKeyword("fs20"); // 字体大小
  w.WriteKeyword("cf1");
  w.WriteText("这是第二段文本 宋体 左对齐 ABC12345");
  // 结束输出
  w.WriteEndGroup();
  }
  #endregion
  /// 
  /// 初始化对象
  /// 
  /// 文本书写器
  public RTFWriter( System.IO.TextWriter w )
  {
  myWriter = w ;
  }
  /// 
  /// 初始化对象
  /// 
  /// 文件名
  public RTFWriter( string strFileName )
  {
  myWriter = new System.IO.StreamWriter(
  strFileName ,
  false ,
  System.Text.Encoding.ASCII );
  }
  private System.Text.Encoding myEncoding = System.Text.Encoding.GetEncoding( 936 ) ;
  /// 
  /// 字符编码格式
  /// 
  public System.Text.Encoding Encoding
  {
  get{ return myEncoding ;}
  set{ myEncoding = value;}
  }
  /// 
  /// 内置的文本书写器
  /// 
  private System.IO.TextWriter myWriter = null;
  private bool bolIndent = false;
  /// 
  /// 是否使用缩进
  /// 
  /// 
  /// RTF文档内部不能随便缩进,提供此选项只是用于生成便于阅读的RTF文档,便于程序的调试,
  /// 在开发调试中可以设置该属性为true,方便开发者能直接查看生成的RTF文档,但在生成最终运行的
  /// 程序时应当设置该属性为 false .
  /// 
  public bool Indent
  {
  get{ return bolIndent ;}
  set{ bolIndent = value;}
  }
  private string strIndentString = " ";
  /// 
  /// 缩进字符串
  /// 
  public string IndentString
  {
  get{ return strIndentString ;}
  set{ strIndentString = value;}
  }
  /// 
  /// 当前缩进层次
  /// 
  private int intGroupLevel = 0 ;
  /// 
  /// 关闭对象
  /// 
  public void Close()
  {
  if(this.intGroupLevel > 0 )
  throw new System.Exception("还有组未写完");
  if( myWriter != null )
  {
  myWriter.Close();
  myWriter = null;
  }
  }
  /// 
  /// 输出一个组
  /// 
  /// 关键字
  public void WriteGroup( string KeyWord )
  {
  this.WriteStartGroup();
  this.WriteKeyword( KeyWord );
  this.WriteEndGroup();
  }
  /// 
  /// 开始输出组
  /// 
  public void WriteStartGroup( )
  {
  if( bolIndent )
  {
  InnerWriteNewLine();
  myWriter.Write("{");
  }
  else
  myWriter.Write("{");
  intGroupLevel ++ ;
  }
  /// 
  /// 结束输出组
  /// 
  public void WriteEndGroup()
  {
  intGroupLevel -- ;
  if( intGroupLevel < 0 )
  throw new System.Exception("组不匹配");
  if( bolIndent )
  {
  InnerWriteNewLine();
  InnerWrite("}");
  }
  else
  InnerWrite("}");
  }
  /// 
  /// 输出原始文本
  /// 
  /// 文本值
  public void WriteRaw( string txt )
  {
  if( txt != null && txt.Length > 0 )
  {
  InnerWrite( txt );
  }
  }
  /// 
  /// 输出关键字
  /// 
  /// 关键字值
  public void WriteKeyword( string Keyword )
  {
  WriteKeyword( Keyword , false );
  }
  /// 
  /// 输出关键字
  /// 
  /// 关键字值
  /// 是否是扩展关键字
  public void WriteKeyword( string Keyword , bool Ext)
  {
  if( Keyword == null || Keyword.Length == 0)
  throw new System.ArgumentNullException("值不得为空");
  if( bolIndent == false && ( Keyword == "par" || Keyword == "pard" ) )
  {
  // par 或 pard 前可以输出空白行,不影响RTF文档显示
  InnerWrite( System.Environment.NewLine );
  }
  if( this.bolIndent )
  {
  if( Keyword == "par" || Keyword == "pard" )
  {
  this.InnerWriteNewLine();
  }
  }
  if( Ext )
  InnerWrite("\\*\\");
  else
  InnerWrite("\\");
  InnerWrite( Keyword );
  }
  /// 
  /// 内容文本编码格式
  /// 
  private System.Text.Encoding Unicode = System.Text.Encoding.Unicode ;
  /// 
  /// 输出纯文本
  /// 
  /// 文本值
  public void WriteText( string Text )
  {
  if( Text == null || Text.Length == 0 )
  return ;
  InnerWrite(' ');
  for( int iCount = 0 ; iCount < Text.Length ; iCount ++ )
  {
  char c = Text[ iCount ] ;
  if( c == '\t')
  {
  this.WriteKeyword("tab");
  InnerWrite(' ');
  }
  else if( c < 256 )
  {
  if( c > 32 && c < 127 )
  {
  // 出现特殊字符,需要斜线转义
  if( c == '\\' || c == '{' || c == '}' )
  InnerWrite( '\\');
  InnerWrite( c );
  }
  else
  {
  InnerWrite("\\\'");
  WriteByte( ( byte ) c );
  }
  }
  else
  {
  byte[] bs = myEncoding.GetBytes( c.ToString());
  for(int iCount2 = 0 ; iCount2 < bs.Length ; iCount2 ++ )
  {
  InnerWrite("\\\'");
  WriteByte( bs[ iCount2 ] );
  }
  }
  }//for( int iCount = 0 ; iCount < Text.Length ; iCount ++ )
  }
  /// 
  /// 当前位置
  /// 
  private int intPosition = 0 ;
  /// 
  /// 当前行的位置
  /// 
  private int intLineHead = 0 ;
  /// 
  /// 16进制字符组
  /// 
  private const string Hexs = "0123456789abcdef";
  /// 
  /// 输出字节数组
  /// 
  /// 字节数组
  public void WriteBytes( byte[] bs )
  {
  if( bs == null || bs.Length == 0 )
  return ;
  WriteRaw( " " );
  for( int iCount = 0 ; iCount < bs.Length ; iCount ++ )
  {
  if( ( iCount % 32 ) == 0 )
  {
  this.WriteRaw( System.Environment.NewLine );
  this.WriteIndent();
  }
  else if( ( iCount % 8 ) == 0 )
  {
  this.WriteRaw(" ");
  }
  byte b = bs[ iCount ] ;
  int h = ( b & 0xf0 ) >> 4 ;
  int l = b & 0xf ;
  myWriter.Write( Hexs[ h ] );
  myWriter.Write( Hexs[ l ] );
  intPosition += 2 ;
  }
  }
  /// 
  /// 输出一个字节数据
  /// 
  /// 字节数据
  public void WriteByte( byte b )
  {
  int h = ( b & 0xf0 ) >> 4 ;
  int l = b & 0xf ;
  myWriter.Write( Hexs[ h ] );
  myWriter.Write( Hexs[ l ] );
  intPosition += 2 ;
  //FixIndent();
  }
  #region 内部成员 ******************************************************
  private void InnerWrite( char c )
  {
  intPosition ++ ;
  myWriter.Write( c );
  }
  private void InnerWrite( string txt )
  {
  intPosition += txt.Length ;
  myWriter.Write( txt );
  }
  private void FixIndent()
  {
  if( this.bolIndent )
  {
  if( intPosition - intLineHead > 100 )
  InnerWriteNewLine();
  }
  }
  private void InnerWriteNewLine()
  {
  if( this.bolIndent )
  {
  if( intPosition > 0 )
  {
  InnerWrite( System.Environment.NewLine );
  intLineHead = intPosition ;
  WriteIndent();
  }
  }
  }
  private void WriteIndent( )
  {
  if( bolIndent )
  {
  for( int iCount = 0 ; iCount < intGroupLevel ; iCount ++ )
  {
  InnerWrite( this.strIndentString );
  }
  }
  }
  #endregion
  /// 
  /// 销毁对象
  /// 
  public void Dispose()
  {
  this.Close();
  }
  }

你使用VS.NET新建一个C#工程项目后,删除自动生成的Main()函数,然后复制并粘贴这段代码,这样就可以编译运行了。

  在这个RTFWriter的基础上,你可以构造自己的RTF应用了,比如将数据库的数据导出到RTF文档中,使用RTF格式向其他程序传递数据。笔者正在开发的XWriter文本编辑器也使用RTFWriter将编辑的文档保存为RTF格式,而且实际上这篇文章是完全使用XWriter编辑的,然后导出为HTML格式,没有使用MS Word,FrontPage等其他文档编辑器,本文中的代码是在VS.NET的C#代码编辑器中直接复制-粘贴而得。

  本文只是对操作RTF文档提供了一些比较简单的说明,详细内容可以参考MSDN中关于RTF的说明,网络上的资源更是多如牛毛。RTF文档格式原理简单,但内容却不少,它是一种很古老的技术,却一直到现在还在广泛的使用,而且估计还能用上很长一段时期。其实我们在学习不断出现的新技术的时候,也可以注意那些古老的但经过时间考验的技术。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章