1

可能有一些非常简单的答案,但我真的坚持这个。

我编写了一些代码,通过 ftp 获取相当大的 (4GB+) xml 文件,将其作为字符串读取并将文档拆分为较小的部分。最后将较小的文件写入磁盘。

在我的开发人员机器上一切都运行良好,但是当投入生产时,脚本在仅读取了文件的十分之一后突然结束。不抛出异常。每一行代码都按预期执行。它只是在遍历整个文件之前结束。这让我觉得是一些 IIS 或 web.config 设置需要被篡改。

代码在 Umbraco CMS 中作为自定义用户控件运行。服务器是运行 IIS 的 2008 Windows 机器。

有任何想法吗?这是代码:

FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
    request.Credentials = new NetworkCredential("anonymous", "x@y.z");
    request.Method = WebRequestMethods.Ftp.DownloadFile;
    request.Timeout = -1;
    request.KeepAlive = true;
    request.UsePassive = true;
    request.UseBinary = true;
    using (response = (FtpWebResponse)request.GetResponse())
    using (responseStream = response.GetResponseStream())
    using (StreamReader sr = new StreamReader(responseStream))
    {
      ReadStreamIntoNewRecord(fileName, sr, ref progress, ref result);
    }

ReadStreamIntoNewRecord 函数如下所示:

private void ReadStreamIntoNewRecord(string fileName, StreamReader sr, int NumberOfRecordsPerBatch)
{
    string line = "";
    string record = "";
    int i = 0;  
    XDocument xdoc = new XDocument(new XElement("collection"));
    while (sr.Peek() >= 0)
    {
        line = sr.ReadLine();
        if (line.Contains("</record>"))
        {
            xdoc.Element("collection").Add(MakeRecordFromString(record + line));
            record = "";
            i++;
            if (i % NumberOfRecordsPerBatch == 0)
            {
                SaveRecordToFile(fileName, xdoc);
                xdoc = new XDocument(new XElement("collection"));
            }
        }
        else
        {
            record = record + line;
        }

    }
    SaveRecordToFile(fileName, xdoc);            
}
4

1 回答 1

2

哇,将 4GB 文件加载到内存中的字符串中是一个可怕的想法。如果它在磁盘上为 4GB 作为 UTF-8,那么它将在内存中为 8GB,因为所有 .NE 字符串在内存中都是 UTF-16。幸运的是,你并没有真正这样做,你只是说你在描述中。

我相信你应该稍微改变一下while循环。正如所写的那样,当确实有更多数据进入时,它可能会检测到流的不正确结束。改用这个:

while ((line = sr.ReadLine()) != null)
{
    ...
}

除此之外,您最好使用简单StreamWriterXmlTextWriter保存文件而不是XDocument. XDocument将整个文件保存在内存中,旨在更轻松地使用 Linq-to-Xml 进行遍历。您没有使用它,并且可以从更轻的重量等级中受益。

于 2011-05-19T01:08:50.933 回答