Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.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# 大型XML文件的问题_C#_Xml_File_Performance_Large Files - Fatal编程技术网

C# 大型XML文件的问题

C# 大型XML文件的问题,c#,xml,file,performance,large-files,C#,Xml,File,Performance,Large Files,我有16个大型xml文件。当我说大的时候,我说的是千兆字节。其中一个文件超过8 GB。其中有几个超过1GB。这些是从外部供应商处提供给我的 我正在尝试将XML导入数据库,以便将其分解到表中。目前,我一次将10000条记录从文件流到内存中,并插入blob。我将SSI与脚本任务一起使用来完成此任务。这实际上对于所有文件都非常快,除了8GB文件 我无法将整个文件加载到xml文档中。我怎么强调都不过分。那是第1次迭代,文件太大了,以至于系统在处理这些文件时都会锁定,尤其是8GB的文件 我运行了当前的“文

我有16个大型xml文件。当我说大的时候,我说的是千兆字节。其中一个文件超过8 GB。其中有几个超过1GB。这些是从外部供应商处提供给我的


我正在尝试将XML导入数据库,以便将其分解到表中。目前,我一次将10000条记录从文件流到内存中,并插入blob。我将SSI与脚本任务一起使用来完成此任务。这实际上对于所有文件都非常快,除了8GB文件

我无法将整个文件加载到xml文档中。我怎么强调都不过分。那是第1次迭代,文件太大了,以至于系统在处理这些文件时都会锁定,尤其是8GB的文件

我运行了当前的“文件拆分器”,花了7个小时导入xml数据,但仍然没有完成。它从8GB文件中导入了363块10000条记录,但仍然没有完成

仅供参考,以下是我目前如何将文件流式存储到内存中(每次10000条记录)。我在

私有静态IEnumerable SimpleStreamAxis(字符串文件名、字符串匹配名)
{
使用(FileStream-stream=File.OpenRead(文件名))
{
使用(XmlReader=XmlReader.Create(流,新的XmlReaderSettings(){ProhibitDtd=false}))
{
reader.MoveToContent();
while(reader.Read())
{
开关(reader.NodeType)
{
case XmlNodeType.Element:
if(reader.Name==matchName)
{
XElement el=XElement.ReadFrom(reader)作为XElement;
如果(el!=null)
收益率;
}
打破
}
}
reader.Close();
}
stream.Close();
}
}
因此,它在所有文件上都可以正常工作,除了8GB的文件,因为它必须越来越深入地流到文件中,所以需要越来越长的时间

我想做的是将文件分割成更小的块,但是分割器需要更快。这样,拖缆和流程的其余部分可以运行得更快。拆分文件的最佳方式是什么?理想情况下,我会在SSIS中自己将其拆分为代码

编辑:

下面是使用流媒体方法实际分页我的数据的代码

connection = (SqlConnection)cm.AcquireConnection(null);

                int maximumCount = Convert.ToInt32(Dts.Variables["MaximumProductsPerFile"].Value);
                int minMBSize = Convert.ToInt32(Dts.Variables["MinimumMBSize"].Value);
                int maxMBSize = Convert.ToInt32(Dts.Variables["MaximumMBSize"].Value);

                string fileName = Dts.Variables["XmlFileName"].Value.ToString();

                FileInfo info = new FileInfo(fileName);

                long fileMBSize = info.Length / 1048576; //1024 * 1024 bytes in a MB

                if (minMBSize <= fileMBSize && maxMBSize >= fileMBSize)
                {
                    int pageSize = 10000;     //do 2000 products at one time

                    if (maximumCount != 0)
                        pageSize = maximumCount;

                    var page = (from p in SimpleStreamAxis(fileName, "product") select p).Take(pageSize);
                    int current = 0;

                    while (page.Count() > 0)
                    {
                        XElement xml = new XElement("catalog",
                            from p in page
                            select p);

                        SubmitXml(connection, fileName, xml.ToString());

                        //if the maximum count is set, only load the maximum (in one page)
                        if (maximumCount != 0)
                            break;

                        current++;
                        page = (from p in SimpleStreamAxis(fileName, "product") select p).Skip(current * pageSize).Take(pageSize);
                    }
                }
connection=(SqlConnection)cm.AcquireConnection(null);
int maximumCount=Convert.ToInt32(Dts.Variables[“MaximumProductsPerFile”].Value);
int minMBSize=Convert.ToInt32(Dts.Variables[“MinimumMBSize”].Value);
int maxMBSize=Convert.ToInt32(Dts.Variables[“maximumbsize”].Value);
字符串文件名=Dts.Variables[“XmlFileName”].Value.ToString();
FileInfo=newfileinfo(文件名);
long fileMBSize=info.Length/1048576//MB中的1024*1024字节
if(minMBSize=fileMBSize)
{
int pageSize=10000;//一次处理2000个产品
如果(最大计数!=0)
pageSize=最大计数;
var page=(从SimpleStreamAxis中的p(文件名,“产品”)选择p);
int电流=0;
而(page.Count()>0)
{
XElement xml=新XElement(“目录”,
从第页的p开始
选择p);
SubmitXml(连接,文件名,xml.ToString());
//如果设置了最大计数,则仅加载最大值(在一页中)
如果(最大计数!=0)
打破
电流++;
页面=(从SimpleStreamAxis(文件名,“产品”)中的p选择p)。跳过(当前*页面大小)。获取(页面大小);
}
}

看看这个项目,它将XML文件拆分成更小的文件来解决您的问题:

将大型XML文件拆分为小型文件:

您需要一个用于处理大型XML文件的SAXReader。

您研究过使用SAX解析器吗?微软没有发布过一个,但网上有一些例子。使用SAX解析器,您基本上可以将文件作为流读取,并触发事件,您可以监听vs将整个过程加载到内存DOM中,这显然是无法做到的。我对使用SAX解析器不太了解,所以我没有具体的建议,但是很多Java人员已经用这种方式编写XML很多年了。

看起来您每一步都在反复读取XML文件,每次使用SimpleStreamAxis中的
from p
位都在重新读取和扫描文件。此外,通过调用Count(),您每次都可以浏览整个页面

试着这样做:

var full = (from p in SimpleStreamAxis(fileName, "product") select p);
int current = 0;

while (full.Any() > 0)
{
    var page = full.Take(pageSize);

    XElement xml = new XElement("catalog",
    from p in page
    select p);

    SubmitXml(connection, fileName, xml.ToString());

    //if the maximum count is set, only load the maximum (in one page)
    if (maximumCount != 0)
        break;

    current++;
    full = full.Skip(pageSize);
}
var full = (from p in SimpleStreamAxis(fileName, "product") select p);
int current = 0;

XElement xml = new XElement("catalog");
int pageIndex = 0;

foreach (var element in full)
{
    xml.Add(element);

    pageIndex++;
    if (pageIndex == pageSize)
    {
        SubmitXml(connection, fileName, xml.ToString());
        xml = new XElement("catalog");
        pageIndex = 0;
    }

    //if the maximum count is set, only load the maximum (in one page)
    if (maximumCount != 0)
        break;

    current++;
}

    // Submit the remainder
if (xml.Elements().Any())
{
    SubmitXml(connection, fileName, xml.ToString());
}
注意,这是未经测试的,但你应该有希望得到这个想法。您需要避免多次枚举文件,在8gb xml文件上,像Count()和Take/Skip这样的操作将花费很长时间

更新:我认为上面的内容仍然会在文件中重复超过我们想要的次数,您需要一些更可预测的内容,例如:

var full = (from p in SimpleStreamAxis(fileName, "product") select p);
int current = 0;

while (full.Any() > 0)
{
    var page = full.Take(pageSize);

    XElement xml = new XElement("catalog",
    from p in page
    select p);

    SubmitXml(connection, fileName, xml.ToString());

    //if the maximum count is set, only load the maximum (in one page)
    if (maximumCount != 0)
        break;

    current++;
    full = full.Skip(pageSize);
}
var full = (from p in SimpleStreamAxis(fileName, "product") select p);
int current = 0;

XElement xml = new XElement("catalog");
int pageIndex = 0;

foreach (var element in full)
{
    xml.Add(element);

    pageIndex++;
    if (pageIndex == pageSize)
    {
        SubmitXml(connection, fileName, xml.ToString());
        xml = new XElement("catalog");
        pageIndex = 0;
    }

    //if the maximum count is set, only load the maximum (in one page)
    if (maximumCount != 0)
        break;

    current++;
}

    // Submit the remainder
if (xml.Elements().Any())
{
    SubmitXml(connection, fileName, xml.ToString());
}

如果您使用的是MS SQL Server,请使用XML批量加载来实现这一点。

我已经看过了,排除了这个可能性。下载中未提供源代码。显示的代码不完整(方法调用未提供的代码)。我也不确定该方法与我已经拆分xml.XmlReade的方式相比有什么速度优势