如何查找用于读取大文本文件的控制字符?

时间:2016-11-29 20:43:21

标签: .net xml streamreader

问题:我有一个非常大的(300MB +)文本文件,它使用STX和ETX控制字符进行一些有趣的格式化。例如:

public System.Web.UI.Page requestVar;

有数百个(如果不是数千个)我称之为“块”的xml消息,每个消息都封装在STX和ETX控制字符之间。这些消息可以跨越多行,而不仅仅是一行。

在解析文件时,我需要能够找到每个xml块以进行单独解析。

我假设一个简单的缓冲流阅读器可以在这里工作,但我需要能够跟踪我正在阅读的位置,以便在控制字符之间拉出每个单独的xml块,直到我到达文件的末尾。

我想我可以用这个简单的方法读取文件:

public System.Web.UI.Page requestVar = new Page();

但是,在处理这些STX和ETX控制字符时,如何设置索引(开始/结束)?

2 个答案:

答案 0 :(得分:0)

尝试以下代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        const string INPUT_FILENAME = @"c:\temp\test1.txt";
        const string OUTPUT_FILENAME = @"c:\temp\test2.txt";

        enum State
        {
            FIND_STX,
            READ_DATA
        }
        static void Main(string[] args)
        {
            char STX = Encoding.UTF8.GetString(new byte[] { 0x02 }).First();
            char ETX = Encoding.UTF8.GetString(new byte[] { 0x03 }).First();

            string testMessage = string.Format("plain txt info{0}<xml ..xml message data.. /xml>{1}", STX, ETX);

            StreamReader reader = null;
            StreamWriter writer = null;

            //write test output file
            writer = new StreamWriter(INPUT_FILENAME, false, Encoding.UTF8);
            for (int i = 0; i < 100; i++)
            {
                writer.WriteLine(testMessage);
            }
            writer.Flush();
            writer.Close();

            //now read test file
            reader = new StreamReader(INPUT_FILENAME, Encoding.UTF8);
            writer = new StreamWriter(OUTPUT_FILENAME, false, Encoding.UTF8);

            char[] newChar = new char[1];
            State state = State.FIND_STX;
            while (!reader.EndOfStream)
            {
                reader.Read(newChar, 0, 1);
                switch (state)
                {
                    case State.FIND_STX :
                        if (newChar[0] == STX)
                        {
                            state = State.READ_DATA;
                        }
                        break;
                    case State.READ_DATA :
                        if (newChar[0] == ETX)
                        {
                            state = State.FIND_STX;
                        }
                        else
                        {
                            writer.Write(newChar[0]);
                        }
                        break;
                }
            }
            writer.Flush();
            writer.Close();
            reader.Close();
        }
    }
}

答案 1 :(得分:0)

使用一些VB,这是我到目前为止所提出的,这是有效但似乎非常低效。

Dim sr As New StreamReader(dataFile)
Dim line As String = ""
Dim text As String = ""

While sr.Peek > -1

    line = sr.ReadLine
    Dim startPos = line.IndexOf(Chr(2)) + 1
    Dim isTrue As Boolean = True
    While isTrue
        'if line contains ETX, get its position else just keep reading
         Dim endPos = line.IndexOf(Chr(3))
         If endPos = -1 Then
              text += line.Substring(startPos)
              line = sr.ReadLine
              startPos = 0
         Else                            
              text += line.Substring(startPos, line.LastIndexOf(Chr(3)))
              isTrue = False
         End If
    End While
    'do something with the text here then reset text and keep going
    text = ""

End While

这实际上设置了&#34; text&#34;是一个完整的xml消息,这是我正在寻找的,但我想知道这是否足够有效的非常大的文件。