1

これには非常に簡単な答えがあるかもしれませんが、私は本当にこれにこだわっています。

ftp を介して非常に大きな (4 GB 以上) xml ファイルをフェッチし、それを文字列として読み取り、ドキュメントを小さな部分に分割するコードをいくつか作成しました。最後に、小さいファイルがディスクに書き込まれます。

私の開発者用マシンではすべて問題なく動作しますが、本番環境に移行すると、スクリプトはファイルの 10 分の 1 を読み取っただけで突然終了します。例外はスローされません。コードのすべての行が期待どおりに実行されます。ファイル全体を処理する前に終了します。これにより、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のファイルをメモリ内の文字列にロードするのは恐ろしい考えです。ディスク上でUTF-8として4GBの場合、すべての.NE文字列がメモリ内でUTF-16であるため、メモリ内で8GBになります。幸いなことに、あなたは実際にはそれをしていません、あなたはあなたが説明の中にいると言っただけです。

whileループを少し変更する必要があると思います。書かれているように、実際に多くのデータが入ってくると、ストリームの不適切な終了を検出している可能性があります。代わりにこれを使用してください。

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

StreamWriterそれに加えて、の代わりに単純なファイルを使用するかXmlTextWriter、ファイルを保存する方がはるかに良いでしょうXDocumentXDocumentファイル全体をメモリに保持し、Linq-to-Xmlで簡単にトラバースできるように設計されています。あなたはそれを使用しておらず、はるかに軽量なクラスの恩恵を受けることができます。

于 2011-05-19T01:08:50.933 に答える