这是解析FIX格式的大字符串的有效方法吗?

时间:2014-05-15 10:30:02

标签: c# string parsing fix-protocol

我需要尽快解析FIX消息。

我的方法如下。我在FP_FixString中保留了对FixString的引用,然后我按顺序完成了我需要的Tag值。

修复消息很大(我需要提取大约4,000个字符和大约100个重复的3个标记组)。

我是否尽可能高效地做到这一点?从字符串构建和解析角度来看?

public FixParser
{
        string FP_FixString;
        int FP_m;
        int FP_Lastm;

        public void Go()
        {
            using (StreamReader reader = new StreamReader(new GZipStream(File.OpenRead(@"L:\Logs\FIX.4.2-D.messages.current.log.20140512T.gz"), CompressionMode.Decompress)))
            {
                string line = "";
                while ( (line = reader.ReadLine()) != null)
                {

                      InitiateFixParse(ref line);

                      string Symbol;
                      if (!GetTagString(55, out Symbol))
                      return;

                      //DO ALL OTHER PROCESSING OF TAGS HERE
                }
        }


        public void InitiateFixParse(ref string fixString)
        {
            FP_Lastm = fixString.Length - 1;
            FP_FixString = fixString;
            FP_m = 0;
        }

       public bool IsEndMark()
        {
            if (FP_m>=FP_Lastm || FP_FixString[FP_m].Equals('\x01'))
                return true;

            return false;
        }

        public bool NextTag(out int Tag, out string ValueString)
        {
            Tag = 0;
            ValueString = "";
            if(FP_m>=FP_Lastm)
                return false;

            string TagString = "";
            bool GettingTag=true;
            while (!IsEndMark())
            {
                if (FP_FixString[FP_m].Equals('='))
                {
                    GettingTag = false;
                    FP_m++;
                }
                if(GettingTag)
                    TagString = TagString + FP_FixString[FP_m];
                else
                    ValueString = ValueString + FP_FixString[FP_m];
                FP_m++;
            }

            Tag=int.Parse(TagString);
            FP_m++; //Start of next Tag

            return true;
        }

        public bool GetTagString(int Tag, out string ValueString)
        {
            //bool FountIt = false;
            int aTag;
            string aValueString;
            while (NextTag(out aTag, out aValueString))
            {
                if (aTag == Tag)
                {
                    ValueString = aValueString;
                    return true;
                }
            }

            ValueString = "";
            return false;
        }
}

2 个答案:

答案 0 :(得分:1)

我乍一看的唯一建议是用StringBuilders替换循环中的字符串连接,例如TagString = TagString + FP_FixString[FP_m];

StringBuilder sb = new StringBuilder();
while (!IsEndMark())
{
   sb.append(FP_FixString[FP_m]);
}
TagString = sb.ToString();

因为StringBuilder 比循环中的连接更有效。通常的警告适用。我同意@DumbCoder的分析是一个好主意。

另外,最好存储消息的FIXml表示,并尽可能使用xpath提取数据(即如果您不是要尝试解析自动创建的日志),因为它可以帮助解决一些问题。重复小组问题,或者说它在我这里做了!

答案 1 :(得分:0)

如果您正在处理非常大的文件,您希望尽可能地避免GC压力,如前所述。 StringBuilder有帮助,但您仍在创建StringBuilder实例。一些快速的胜利:

if (GettingTag)
{
    //TagString = TagString + FP_FixString[FP_m];
    Tag = Tag * 10 + ((byte)FP_FixString[FP_m] -48);
}// This reduces time by about 40%

//Tag = int.Parse(TagString);

以下代码进一步缩短了时间(减少到原始时间的50%):

int valueStart = 0;
while (!IsEndMark())
{
    if (FP_FixString[FP_m].Equals('='))
    {
        GettingTag = false;
        FP_m++;
        valueStart = FP_m;
    }
    if (GettingTag)
    {
        //TagString = TagString + FP_FixString[FP_m];
        Tag = Tag * 10 + ((byte)FP_FixString[FP_m] -48);
    }
    //else
        //ValueString = ValueString + FP_FixString[FP_m];
    FP_m++;
}
ValueString = FP_FixString.Substring(valueStart, FP_m - valueStart);

//Tag = int.Parse(TagString);
FP_m++; //Start of next Tag

我没有进一步查看代码。