Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 超大单行文件解析_C#_String_File Io - Fatal编程技术网

C# 超大单行文件解析

C# 超大单行文件解析,c#,string,file-io,C#,String,File Io,我正在从一个站点下载数据,该站点以非常大的块向我提供数据。在非常大的块中,有一些“块”需要单独解析。这些“块”以“(ClinicalData)”开头,以“(/ClinicalData)”结尾。因此,示例字符串如下所示: (ClinicalData)(ID="1")(/ClinicalData)(ClinicalData)(ID="2")(/ClinicalData)(ClinicalData)(ID="3")(/ClinicalData)(ClinicalData)(ID="4")(/Clini

我正在从一个站点下载数据,该站点以非常大的块向我提供数据。在非常大的块中,有一些“块”需要单独解析。这些“块”以“(ClinicalData)”开头,以“(/ClinicalData)”结尾。因此,示例字符串如下所示:

(ClinicalData)(ID="1")(/ClinicalData)(ClinicalData)(ID="2")(/ClinicalData)(ClinicalData)(ID="3")(/ClinicalData)(ClinicalData)(ID="4")(/ClinicalData)(ClinicalData)(ID="5")(/ClinicalData)
enum ReadState
{
    Start,
    SawOpen
}


using (var sr = new StreamReader(@"path\to\clinic.txt"))
using (var sw = new StreamWriter(@"path\to\output.txt"))
{
    var rs = ReadState.Start;
    while (true)
    {
        var r = sr.Read();
        if (r < 0)
        {
            if (rs == ReadState.SawOpen)
                sw.Write('<');
            break;
        }

        char c = (char) r;
        if ((c == '\r') || (c == '\n'))
            continue;

        if (rs == ReadState.SawOpen)
        {
            if (c == 'C')
                sw.WriteLine();

            sw.Write('<');
            rs = ReadState.Start;
        }

        if (c == '<')
        {
            rs = ReadState.SawOpen;
            continue;
        }

        sw.Write(c);
    }
}
在“理想”情况下,块是指一行数据,但有时会出现错误的换行符。因为我想解析块中的(ClinicalData)块,所以我想让我的数据能够逐行解析。因此,我将文本文件读入StringBuilder,删除新行(以防万一),然后插入自己的新行,这样我就可以逐行读取

StringBuilder dataToWrite = new StringBuilder(File.ReadAllText(filepath), Int32.MaxValue);

// Need to clear newline characters just in case they exist.
dataToWrite.Replace("\n", "");

// set my own newline characters so the data becomes parse-able by line 
dataToWrite.Replace("<ClinicalData", "\n<ClinicalData");

// set the data back into a file, which is then used in a StreamReader to parse by lines.
File.WriteAllText(filepath, dataToWrite.ToString());
StringBuilder-dataToWrite=new-StringBuilder(File.ReadAllText(filepath),Int32.MaxValue);
//需要清除换行符,以防它们存在。
dataToWrite.Replace(“\n”和“);
//设置我自己的换行符,以便数据可以按行解析

dataToWrite.Replace(“首先,我认为您不需要将所有文本放入StringBuilder中,因为您甚至不需要将部分连接到它。您可以尝试以下操作:

File.ReadAllText(filepath).Replace("\n", "").Replace("<ClinicalData", "\n<ClinicalData");
有很多方法可以实现类似的东西,但希望这能帮助您开始

StreamReader的ReadLine()方法只是从文件中读取文本的多种方法之一。您可以将文本读入指定长度的缓冲区,然后解析出ClinicalData标记。如果您愿意,我可以提供一个示例。

或者,如果您正在读取XML文件,XmlReader是另一个选项。

这是一种非常低效的读取文本文件的方法,更不用说大的文本文件了。如果您只需要一次传递、替换或添加单个字符,则应使用
StreamReader
。如果您只需要一个前瞻字符,则只需保持一个中间状态,例如:

(ClinicalData)(ID="1")(/ClinicalData)(ClinicalData)(ID="2")(/ClinicalData)(ClinicalData)(ID="3")(/ClinicalData)(ClinicalData)(ID="4")(/ClinicalData)(ClinicalData)(ID="5")(/ClinicalData)
enum ReadState
{
    Start,
    SawOpen
}


using (var sr = new StreamReader(@"path\to\clinic.txt"))
using (var sw = new StreamWriter(@"path\to\output.txt"))
{
    var rs = ReadState.Start;
    while (true)
    {
        var r = sr.Read();
        if (r < 0)
        {
            if (rs == ReadState.SawOpen)
                sw.Write('<');
            break;
        }

        char c = (char) r;
        if ((c == '\r') || (c == '\n'))
            continue;

        if (rs == ReadState.SawOpen)
        {
            if (c == 'C')
                sw.WriteLine();

            sw.Write('<');
            rs = ReadState.Start;
        }

        if (c == '<')
        {
            rs = ReadState.SawOpen;
            continue;
        }

        sw.Write(c);
    }
}
enum ReadState
{
开始
锯开
}
使用(var sr=new StreamReader(@“path\to\clinic.txt”))
使用(var sw=new StreamWriter(@“path\to\output.txt”))
{
var rs=ReadState.Start;
while(true)
{
var r=sr.Read();
if(r<0)
{
if(rs==ReadState.SawOpen)

sw.Write('您不是要求前面有一个2GB容量的StringBuilder吗?您会得到哪一行异常?您还可以在StringBuilder之前将File.ReadAllText(filepath)放在一个单独的语句中并进行测试吗?如果您在读取非常大的文件时遇到问题,请尝试使用“MemoryMappedFile”。看看它是否解决了这个问题'(ClinicalData)(ID=“1”)(/ClinicalData)”在您的示例中应该是“”?到500-内部服务器错误:我认为我也是,但这是一行失败的280MB文本。到Furkan Omay:在创建StringBuilder时发生异常。我不认为错误是由于File.ReadAllText造成的,因为我可以执行:String[]contents=File.ReadAllLines(filepath);一切都很好(我知道它们是不同的方法)。内容数组在我尝试访问它时就会失败。此外,由于所有数据都在一行中,因此内容的大小为1。对于用户2012384:MemoryMapping不起作用,因为您必须读取TechUnks,正如最初指定的那样,我失败了。回到办公室后,我将尝试您的一体化声明,谢谢Arin。我不使用StreamReader,因为在我选择的“块大小”切掉了我所需“块”的中间部分的情况下,我无法想出可以创建我所需块的逻辑。例如(不是一个确切的测试用例),使用我最初发布的块:Pass 1:“(ClinicalData)(ID=“1”)(/ClinicalData)(Clin“Pass2:”icalData)(ID=“2”)(/ClinicalDa“Pass 3:“ta”(ClinicalData)(ID=“3”)(/ClinicalData)(ClinicalData)(ID=“4”)(/Cl”Pass 4:“inicalData)(ClinicalData)(ID=“5”)(/ClinicalData)”。让您在Pass上停下来:我无法确定要分析的每个所需“块”的确切大小,因为某些块具有附加属性,而其他块如果留空则不会具有这些属性。例如:(ClinicalData)(ID=“1”)(Name=“Scooter”)(/ClinicalData)(ClinicalData)(ID=“2”)(/ClinicalData)。最后:我收到的数据不是真正的XML格式,因此结构无法解析。我熟悉XML解析和LINQ to XML,遗憾的是我不能使用它。是的,但假设您的第一块代码中有3个半ClientData标记。您可以解析这3个ClientData标记,然后将字符串的其余部分存储在内存中的某个位置y、 加载下一个块并将第一个块中剩余的字符串附加到开头并重复。对,我未能正确实现的部分是能够将字符串拆分为块,同时将剩余的字符串保留在内存中以便与下一个解析的块连接。感谢Dour High Arch的深入研究我会给你一次一个字符的方法,稍作修改。1)保留字符的集合,以便我可以跟踪已完成的块,从而允许我通过行解析为将来编写行。请注意,此代码无法处理CDATA部分中不匹配的
字符。处理这些字符需要额外的
读取状态。
enum ReadState
{
    Start,
    SawOpen
}


using (var sr = new StreamReader(@"path\to\clinic.txt"))
using (var sw = new StreamWriter(@"path\to\output.txt"))
{
    var rs = ReadState.Start;
    while (true)
    {
        var r = sr.Read();
        if (r < 0)
        {
            if (rs == ReadState.SawOpen)
                sw.Write('<');
            break;
        }

        char c = (char) r;
        if ((c == '\r') || (c == '\n'))
            continue;

        if (rs == ReadState.SawOpen)
        {
            if (c == 'C')
                sw.WriteLine();

            sw.Write('<');
            rs = ReadState.Start;
        }

        if (c == '<')
        {
            rs = ReadState.SawOpen;
            continue;
        }

        sw.Write(c);
    }
}