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

本文关键字:Maxvalue int xml 文件 | 更新日期: 2023-09-27 18:10:56

我无法在接近300 GB的xml文件中获得linenumber。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());
        }
    }

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

你可以尝试的不多:

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)编写自己的XmlReader,使用BigInteger

在用dotpeek调查了一下之后,似乎问题深深植根于内部XmlTextReaderImpl类(这应该是您正在使用的阅读器的实际类型)和它正在使用的内部类型:

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

如果你想用最少的工作来实现这一点,我建议你获得。net源代码,通过复制XmlTextReaderImpl(和所有相关的内部类型)创建自己的Xml阅读器,用BigInteger s替换所有行号int s。如果您想隐藏类型,您可能需要创建一个IXmlBigLineInfo或类似的接口,并使用它而不是IXmlLineInfo