首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将文本列中的RTF大容量转换为纯文本

将文本列中的RTF大容量转换为纯文本
EN

Database Administration用户
提问于 2012-05-04 13:37:31
回答 4查看 27.3K关注 0票数 8

我有一个遗留系统,表中有大约1000万行。在该表中有一个类型为text的列,其中大多数是标准文本,但其中大约有50万行有RTF标记。我需要将RTF格式的文本转换为纯文本。

我的当前方法是,我有一个C#程序,它使用SqlDataAdapter将查询加载到DataTable中,并使用winforms RichTextBox控件进行转换。

代码语言:javascript
运行
复制
void bw_DoWork(object sender, DoWorkEventArgs e)
{
    count = 0;

    rtbRTFToPlain = new RichTextBox();

    using (SqlDataAdapter ada = new SqlDataAdapter("select note_guid, notes from client_notes", Globals.SQLConnectionString))
    using(SqlCommandBuilder cmb = new SqlCommandBuilder(ada))
    {
        DataTable dt = new DataTable();
        ada.UpdateCommand = cmb.GetUpdateCommand();

        ada.Fill(dt);

        int reportEvery = dt.Rows.Count / 100;
        if (reportEvery == 0)
            reportEvery = 1;
        foreach (DataRow row in dt.Rows)
        {
            if (count % reportEvery == 0)
                bw.ReportProgress(count / reportEvery);

            try
            {
                if (((string)row["notes"]).TrimStart().StartsWith("{") == true)
                {
                    rtbRTFToPlain.Rtf = (string)row["notes"];
                    row["notes"] = rtbRTFToPlain.Text;
                }
            }
            catch
            {
            }

            count++;

        }
        bw.ReportProgress(100);

        this.Invoke(new Action(() => 
            {
                this.ControlBox = false;
                this.Text = "Updating database please wait";
            }));
        ada.Update(dt);
    }
}

这对于小型表非常有用,但是这是我第一次在一个拥有如此大的数据集的表上运行它(有些rtf文件可以有几兆字节大小的嵌入图片),而且我的C#程序正在获取C#错误。

我知道我可以把我的查询分成一个更小的批次,但是我想知道是否有更好的方法来去除RTF格式。

我应该只做与当前解决方案相同的事情,而只是一次查询较小的数据块,还是有更好的方法来做到这一点?

EN

回答 4

Database Administration用户

回答已采纳

发布于 2012-05-04 20:21:16

最后,我创建了一个CLR函数来转换它。

我找到了这个图书馆,然后对它做了一些调整,删除了一些我不需要的东西,比如日志记录和绘图方法,这样我就可以把它标记为安全了。

然后我就上了这个小班。

代码语言:javascript
运行
复制
using System.Data.SqlTypes;
using Itenso.Rtf.Converter.Text;
using Itenso.Rtf.Support;

public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlString RtfToPlainText(SqlString text)
    {
        if (text.Value.StartsWith(@"{\rtf"))
        {
            RtfTextConverter textConverter = new RtfTextConverter();
            RtfInterpreterTool.Interpret(text.Value, textConverter);
            return textConverter.PlainText;
        }
        else
            return text;
    }
}

并在SQL中运行此程序。

代码语言:javascript
运行
复制
sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO

CREATE ASSEMBLY ConversionsSqlExtensionsAssembly 
from 'E:\Code\ConversionsSqlExtensions\bin\Debug\ConversionsSqlExtensions.dll' 
WITH PERMISSION_SET = safe
go

CREATE function RtfToPlainText(@value nvarchar(max))
returns nvarchar(max)
AS EXTERNAL NAME ConversionsSqlExtensionsAssembly.StoredProcedures.RtfToPlainText

而且速度快,效果很好!

票数 5
EN

Database Administration用户

发布于 2014-05-30 18:47:26

我和使用Itenso做了同样的事情,但在我的例子中,在我的SQL2008R2数据库中将其标记为安全之前,还有很多工作要做。

首先,像Scott一样,我不得不删除对System.Drawing的引用。我发现最简单的方法是删除引用,重新编译,然后重写使用库的代码。在大多数情况下,我只是从使用它的VOID函数中删除了所有代码,并且在我无法将绘图/Color对象更改为"object“对象的情况下。

我必须做的另一件事是删除对log4net的任何和所有引用,因为它引用的库System.DirectoryServices也不能被标记为安全。这有点困难,但总的来说,我也采取了同样的方法。

最后,在我这样做之后,我收到了关于设置静态值的抱怨,这在安全的CLR函数中是不允许的。因此,我更新了代码,将所有静态值更改为READONLY,这起了作用(这几乎是在代码的“日志”部分,而我并不真正关心这个部分)。

我的最终CLR代码如下所示:

代码语言:javascript
运行
复制
[Microsoft.SqlServer.Server.SqlFunction]
[return: SqlFacet(MaxSize=-1)]
public static SqlChars RTFFix([SqlFacet(MaxSize=-1)]string rtfField)
{
    SqlChars returnChars;
    try
    {

        RtfTextConverter textConverter = new RtfTextConverter();
        RtfInterpreterTool.Interpret(rtfField, textConverter);
        returnChars = new SqlChars(new SqlString(textConverter.PlainText.Trim()));
    }
    catch (Exception e)
    {
        returnChars = new SqlChars(new SqlString(rtfField));
    }
    return returnChars;
}
票数 2
EN

Database Administration用户

发布于 2012-05-04 15:43:41

我编写了一个小的SQL函数,将文本从带标记的字符串中删除:http://cookingwithsql.com/index.php?option=com_content&task=view&id=65&Itemid=60

不幸的是,它只处理多达8000个字符的字符串数据。如果您正在SQL 2005和更高版本上运行,也许可以将其更改为使用varchar(max)。

用法:

代码语言:javascript
运行
复制
select dbo.ScrapeText('<I love SQL> gobbldygook font 12 blah blah') as 'Result'

Result
----------------------------
I love SQL

我会在这里张贴消息来源,以供快速参考。

代码语言:javascript
运行
复制
use master
IF (object_id('dbo.ScrapeText') IS NOT NULL)
BEGIN
  PRINT 'Dropping: dbo.ScrapeText'
  DROP function dbo.ScrapeText
END
GO
PRINT 'Creating: dbo.ScrapeText'
GO
CREATE FUNCTION dbo.ScrapeText 
(
  @string varchar(8000)
) 
returns varchar(8000)

AS
BEGIN
---------------------------------------------------------------------------------------------------
-- Title:        ScrapeText
--               
-- Date Created: April 4, 2006
--               
-- Author:       William McEvoy
--               
-- Description:  This function will attempt to remove markup language formatting from a string. This is 
--               accomplished by concetenating all text contained between greater than and less 
--               than signs within the formatted text.  
--               
---------------------------------------------------------------------------------------------------
-- Date Revised: 
-- Author:       
-- Reason:       
---------------------------------------------------------------------------------------------------

declare @text  varchar(8000),
        @PenDown char(1),
        @char  char(1),
        @len   int,
        @count int

select  @count = 0,
        @len   = 0,
        @text  = ''


---------------------------------------------------------------------------------------------------
-- M A I N   P R O C E S S I N G
---------------------------------------------------------------------------------------------------

-- Add tokens
select @string = '>' + @string + '<'

-- Replace Special Characters
select @string = replace(@string,' ',' ')

-- Parse out the formatting codes
select @len = len(@string)
while (@count <= @len)
begin
  select @char = substring(@string,@count,1)

  if (@char = '>')
     select @PenDown = 'Y'
  else 
  if (@char = '<')
    select @PenDown = 'N'
  else  
  if (@PenDown = 'Y')
    select @text = @text + @char

  select @count = @count + 1
end

RETURN @text
END
GO
IF (object_id('dbo.ScrapeText') IS NOT NULL)
  PRINT 'Function created.'
ELSE
  PRINT 'Function NOT created.'
GO
票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/17454

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档