当超过int.Maxvalue时,如何在xml文件中获取行号

时间:2014-06-30 18:35:40

标签: c# .net xml

我无法在近300 GB的xml文件中获取亚麻布。 IXmlLineInfo.LineNumber是一个int32,当它超过int.MaxValue时,返回一个负数。如果我使用int或long来存储亚麻布,那就没有区别了。 Xmlreader能够读取到eof。 使用.net 2.0和最新版本也使用int32。

public void ReadLines()
    {
        long readcounter = 0;
        long linenumber = 0;
        fname = "I:\\XML Files\\europe-latest.osm";
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.ProhibitDtd = false;
        settings.XmlResolver = null;
        XmlReader reader = XmlReader.Create(fname, settings);

        IXmlLineInfo lineInfo = ((IXmlLineInfo)reader);
        try
        {
            while (reader.Read())
            {
                linenumber = lineInfo.LineNumber;
                readcounter++;
                if (readcounter % 1000000 == 0) Console.WriteLine(linenumber.ToString());
            }
        }
        catch (XmlException ex)
        {
            Console.WriteLine(ex.Message);
            Console.ReadLine();
        }
        finally
        {
            reader.Close();
            Console.WriteLine(DateTime.Now.ToLongTimeString());
        }

    }

2 个答案:

答案 0 :(得分:1)

您无法尝试:

1)使用System.Numerics.BigInteger存储实际行号 - 在每次操作后检查行号是否小于以前,同时在BigInteger中存储实际行号。好吧,在一个非常庞大的文件中,它实际上可以溢出并变得比以前更大(例如,在读取之后,以几个内部增量的50亿行元素):

var actualLine = new System.Numerics.BigInteger(0);

Int32 lastInt32Line = lineInfo.LineNumber;

// Some Xml reading

Int32 diff = lineInfo.LineNumber - lastLine;

// If an overflow has happened - add overflow
if (diff >= 0)
    actualLine += (new BigInteger(Int32.MaxValue)) * 2 - diff;
else // Everything is normal - add the diff
    actualLine += diff;

真正可能的问题是,尽管您正确存储了行号,但XmlReader的内部可能会开始崩溃。在我看来,checked整数算术代码应该是默认值,而不是现在未经检查的 - 当溢出发生时,如果没有明确告知其他类,则该类已损坏。

2)重新组织您的数据存储,以更分散的方式处理数据 3)编写自己的使用BigInteger的XmlReader。

答案 1 :(得分:1)

在用dotpeek稍微研究一下后,问题似乎深深植根于内部XmlTextReaderImpl类(这应该是您正在使用的读者的实际类型),内部类型是使用:

internal struct LineInfo
{
    internal int lineNo;
    internal int linePos;
    // ...
}

如果您希望以最少的工作量来处理此问题,我建议您获取.NET source code,通过复制XmlTextReaderImpl(以及所有相关的内部类型)创建您自己的Xml阅读器,替换所有行号{ {1}} int s。如果要隐藏类型,可能需要创建接口BigInteger或类似接口,并使用它而不是IXmlBigLineInfo

希望这有帮助。