如何在邮件中转义换行符?

时间:2013-11-15 04:14:08

标签: .net log4net

我正在使用log4net和FileAppender。布局模式为"%utcdate %message%newline",因此每条消息都需要1行 但是,包含新行号的消息存在问题;是否可以在写入文件之前逃避新行?

3 个答案:

答案 0 :(得分:4)

您可以创建一个自定义PatternConverter来转义换行符。

这提供了比其他答案更灵活的解决方案,因为您可以将它与任何appender一起使用。

我按照这些文章来实现一个自定义PatternConverter,用空格替换换行符:

https://dejanfajfar.wordpress.com/2011/04/14/log4net-custom-layoutpattern/

http://www.hanselman.com/blog/CreatingYourOwnCustomPatternLayoutPatternParserAndPatternConvertorWithLog4net.aspx

自定义PatternConverter的代码如下所示:

using System.IO;
using log4net.Util;

public class EncodedMessagePatternConvertor : PatternConverter
{
    protected override void Convert(TextWriter writer, object state)
    {
        var loggingEvent = state as log4net.Core.LoggingEvent;

        if (loggingEvent == null)
            return;

        // Replace newline characters with spaces
        var encodedMessage = loggingEvent.RenderedMessage.Replace("\r", " ").Replace("\n", " ");

        writer.Write(encodedMessage);
    }
}

自定义PatternLayout的代码如下所示:

using log4net.Layout;
using log4net.Util;    

public class CustomPatternLayout : PatternLayout
{
    public CustomPatternLayout()
    {
        AddConverter(new ConverterInfo { Name = "encodedmessage", Type = typeof(EncodedMessagePatternConvertor) });
    }
}

appender配置应如下所示:

<appender name="SomeAppender" type"...">
    ...
    <layout type="YourNamespace.CustomPatternLayout, YourAssemblyName">
      <conversionPattern value="%date %-5level %logger %encodedmessage %newline" />
    </layout>
</appender>

我为模式名称选择了“ encodedmessage ”,但您可以通过在AddConverter调用和配置中更改它来为其命名。

此解决方案应该适用于其他编码要求,方法是更改​​Convert方法中的代码以满足您的需求。

答案 1 :(得分:1)

到目前为止,我的解决方案是使用自定义文件追加器:

class MyFileAppender : FileAppender
{
    protected override void Append(LoggingEvent loggingEvent)
    {
        var val = Convert(loggingEvent);
        base.Append(val);
    }

    protected override void Append(LoggingEvent[] loggingEvents)
    {
        var vals = loggingEvents.Select(Convert).ToArray();
        base.Append(vals);
    }

    private static LoggingEvent Convert(LoggingEvent loggingEvent)
    {
        var eventData = loggingEvent.GetLoggingEventData();
        eventData.ExceptionString = Convert(eventData.ExceptionString);
        eventData.Message = Convert(eventData.Message);
        var val = new LoggingEvent(eventData);
        return val;
    }

    static string Convert(object val)
    {
        var res = val.ToString().Replace("\r", "\\r").Replace("\n", "\\n");
        return res;
    }
}

答案 2 :(得分:0)

Avalanchis建议的解决方案。但是,我来到这个线程来寻找在一行中附加异常消息和堆栈跟踪的解决方案。因此,我将Convert方法更改为如下形式:

        protected override void Convert(TextWriter writer, object state)
        {
            var loggingEvent = state as log4net.Core.LoggingEvent;
            string encodedMessage = string.Empty;

            if (loggingEvent == null)
            {
                return;
            }

            // Replace newline characters with <space>
            if (loggingEvent.ExceptionObject == null)
            {
                encodedMessage = loggingEvent.RenderedMessage.Replace("\r\n", " ");
            }
            else
            {
                encodedMessage = loggingEvent.GetExceptionString().Replace("\r\n", " ");
            }

            writer.Write(encodedMessage);
        }

此外,我必须在log4net配置的布局标签中将IgnoresException属性设置为false:

  <layout type="{Namespace}.CustomPatternLayout">
    <IgnoresException value="False" />
    <conversionPattern value="%date %-5level %logger - %encodedmessage%newline" />
  </layout>

这指定不包含异常数据,因为我们已经在编码消息中包含了异常数据。