如何在 BizTalk 管道组件中有效地修改流中的文本?

Posted

技术标签:

【中文标题】如何在 BizTalk 管道组件中有效地修改流中的文本?【英文标题】:How can i modify text in a stream efficiently, in a BizTalk pipeline component? 【发布时间】:2011-06-05 06:41:25 【问题描述】:

我有一个包含文本的流,现在我想在该流中编辑一些文本(替换一些值)。

在不中断流的情况下,最有效的方法是什么? 我想在 BizTalk 的自定义管道组件中使用它。

public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)

    string msg = "";
    using (VirtualStream virtualStream = new VirtualStream(pInMsg.BodyPart.GetOriginalDataStream()))
    
        using(StreamReader sr = new StreamReader(VirtualStream))
        
            msg = sr.ReadToEnd();
        

        // modify string here
        msg = msg.replace("\r\n","");

        while (msg.Contains(" <"))
           msg = msg.Replace(" <", "<");

        VirtualStream outStream = new VirtualStream();
        StreamWriter sw = new StreamWriter(outStream, Encoding.Default);
        sw.Write(msg);
        sw.Flush();
        outStream.Seek(0, SeekOrigin.Begin);

        pInMsg.BodyPart.Data = outStream;
        pContext.ResourceTracker.AddResource(outStream);
    

    return pInMsg;

这是代码,但正如您所见,当我执行sr.ReadToEnd() 时,我正在中断流。

有没有更好的方法来做到这一点?

【问题讨论】:

【参考方案1】:

对于不可搜索的只读流的简单情况,您可以创建一个包装流,根据需要在Stream.Read(可能还有Stream.ReadByte)方法中进行即时替换。但是这些都适用于原始字节,因此您可能还必须考虑流编码。

【讨论】:

您能否详细说明一些代码示例?我没有流媒体经验.. thx【参考方案2】:

您在管道组件中使用 Stream 类这一事实并不像您直观地想象的那样使其成为 流式管道组件本身

最合适的方式是将职责分成两部分:

首先,您创建一个客户System.IO.Stream 类 - 这是一个包装原始传入流并公开流接口的类。在此类中,您将有效地处理调用代码读取的字节。此类不应依赖于 BizTalk,并且您应该能够在 BizTalk 之外为此类创建示例单元测试程序。

对于第一种情况,我建议您浏览到 several articles with source code samples 之一。

其次,管道组件本身,其唯一职责是将传入流替换为您的自定义流的实例。这是一种惯用的模式,您可以在良好的管道组件中找到它。特别是在Execute method 的执行过程中,您不应该读取原始传入流。当Messaging Agent 接管时,读取将自动发生 - 自动

以下 sn-p 应该是Executemethod 的规范源代码,当然,除了用于错误处理的额外代码之外:

IBaseMessage IComponent.Execute(IPipelineContext pContext, IBaseMessage pInMsg)

   // assign a new CustomStream to the incoming message

    System.IO.Stream stream = pInMsg.BodyPart.GetOriginalDataStream();
    System.IO.Stream customStream = new CustomStream(stream);

    // return the message for downstream pipeline components (further down in the pipeline)

    pInMsg.BodyPart.Data = customStream;
    pContext.ResourceTracker.AddResource(customStream);

    return pInMsg;

看到了吗?在前面的方法中没有任何读取。整个处理过程应在自定义 Stream 类中的 Read 方法的(重复)调用期间发生。

正如我在回复the following question 时所写,我强烈建议您查看Nic Barden 撰写的有关开发流式管道组件的整个系列帖子。

【讨论】:

【参考方案3】:

我认为方法是保留一个完成和一个处理缓冲区,然后当您将新内容写入流时,您将其保留在待处理缓冲区中,直到您知道没有其他内容可以替换。 在替换或决定没有什么可以替换之后,将该数据从挂起的缓冲区移动到完成的缓冲区。 read 方法应该只从 done 缓冲区读取,write 应该只写入处理缓冲区,flush 将所有挂起的内容移动到 done。

不关心刷新部分,我正在考虑如何以最好的方式做到这一点,因为我需要编写一个通用字符串替换流。

[edit] 抱歉,回复了一个 2 年前的帖子...[/edit]

【讨论】:

以上是关于如何在 BizTalk 管道组件中有效地修改流中的文本?的主要内容,如果未能解决你的问题,请参考以下文章

BizTalk SMTP 发送带有附件的邮件(无编排,自定义发送管道组件)

BizTalk 中的 FHIR JSON 到 XML 解码

如何在 BizTalk 自定义管道中实现下拉列表

如何有效地计算文档流中的文档之间的相似性

从外部附件输入流中读取并推送到 s3 的最有效方法?

Android有效地从输入流中读取