2016-09-08 8 views
3

Open XML SDKを使用してカスタマイズしたコードでXLSXファイルを作成しています。 200列の50000レコード、最大13 GBのRAMを使用しています。XLSXファイルを作成して100000レコードに時間をとり、最大RAMメモリを使用する

しかし、私は100000行と200列の最大16 GBのRAMを使っていましたが、XLSXファイルを作成せず、RAMメモリの増減を続け、CPU使用量を増減しました。

私はStreamに100000行200列を書き込んで、XMLファイルを分割することなく同時にストリームをPackage Part Streamにコピーしています。そのXMLファイルのサイズは3 GBです。

Open XML SDKを使用してこれを解決することができますか?

私は、シングルユーザー用に200列の100000レコードで動作するOpen XMLを試してみました。しかし、2人のユーザーのために200列の100000レコードを作成すると、サーバーがハングしています。

私のカスタマイズされたコードはRAMを増やしていますが、ハングしません。

以下のコードでは、 "CreateOpenXMLComWorkSheet_XMLWriter"メソッドがRAMサイズを増やしています。

私はあなたの参照のために以下のコードを使用しています。変更が必要な場合はお知らせください。

//Package method 

    Package package = null; 
    using (package = ZipPackage.Open(path, FileMode.Create)) 
    { 

     packgPart = package.CreatePart(new Uri(relativePaths[relIndex], UriKind.Relative), contentTypes[6], CompressionOption.Maximum); 
     XmlWriter xmlWriter; 
     Stream stream = CreateOpenXMLComWorkSheet_XMLWriter(data, "", out xmlWriter); 
     CopyStream(stream, packgPart.GetStream()); 
     xmlWriter.Flush(); 
     xmlWriter.Close(); 
     xmlWriter = null; 
     package.Flush(); 
     packgPart = null; 
     stream.Close(); 
     stream.Dispose(); 
     stream = null; 
     relIndex++; 
     GC.Collect(); 
     package.Close(); 

    } 

    // CreateOpenXMLComWorkSheet method 
    // Define other methods and classes here 
private static Stream CreateOpenXMLComWorkSheet_XMLWriter(List<StringBuilder> rows, string sheet,out XmlWriter xmlWriter) 

{ 

    string[] cols; 

    XmlWriterSettings xmlWriterSettings = new XmlWriterSettings(); 
      xmlWriterSettings.NewLineHandling = NewLineHandling.None; 
      xmlWriterSettings.Indent = false; 
      xmlWriter = null; 
      MemoryStream stream = new MemoryStream(); 
      string nameSpace = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; 
      xmlWriter = XmlWriter.Create(stream,xmlWriterSettings); 

    xmlWriter.WriteStartElement("x","worksheet",nameSpace); 
    xmlWriter.WriteStartElement("x","sheetData",nameSpace); 


    for (m = 0; m < rows.Count; m++) 
    { 

     xmlWriter.WriteStartElement("x","row",nameSpace); 

     cols = rows[m].ToString().Split(new string[] { univDelimiter }, StringSplitOptions.None); 


     for (int i = 1; i <= cols.Length; i++) 
     { 
      cellValue = cols[i - 1]; 
      if (double.TryParse(cellValue,out dVal)) 
      { 
       dataType = "n"; 
      } 
      else 
      { 
       dataType = "str"; 
      } 
      xmlWriter.WriteStartElement("x","c",nameSpace); 
      xmlWriter.WriteAttributeString("s", "13"); 
      xmlWriter.WriteAttributeString("t", dataType); 
      xmlWriter.WriteStartElement("x", "v",nameSpace); 
      xmlWriter.WriteValue(cellValue); 
      xmlWriter.WriteEndElement(); 
      xmlWriter.WriteEndElement(); 
     } 

     xmlWriter.WriteEndElement(); 

     rows[m] = null; 

    } 
    xmlWriter.WriteEndElement(); 
    xmlWriter.WriteEndElement(); 
    xmlWriter.Flush(); 
    stream.Position = 0; 
    return stream; 
} 

//CopyStream method 
private static void CopyStream(Stream source, Stream target) 
{ 
    const int bufSize = 0x1000; 
    byte[] buf = new byte[bufSize]; 
    int bytesRead = 0; 
    while ((bytesRead = source.Read(buf, 0, bufSize)) > 0) 
     target.Write(buf, 0, bytesRead); 
} 
+0

別のスレッドや 'async'の' Task'でファイルを作成してサーバーがハングしないようにできますか? – mcy

+0

あなたはepplusを試しましたか? –

+0

'CompressionOption.Maximum'は最も遅いものなので、比較のために' CompressionOption.Fast'を試すことができます – Slai

答えて

2

ファイルを書き込む際に間違ったアプローチをしているようですが、xml sdkを開いても大量のデータを作成するのに十分なツールです。 私はあなたがメモリを使い果たすことなくxmlreaderとwriterの組み合わせを使うSAXライクなアプローチを取る必要があると思います。

あなたの特定の要件に適合するこの素晴らしいブログをご覧ください。メモリ圧力を減らすために

https://blogs.msdn.microsoft.com/brian_jones/2010/06/22/writing-large-excel-files-with-the-open-xml-sdk/

+0

返信ありがとうございます。 –

+0

それはあなたに役立ったですか?同じ記事に他の記事がありました。http://www.codeproject.com/Articles/877791/How-to-Create-Large-Excel-File-using-Openxml – iSensical

2

はあなたのXmlWriterでのMemoryStreamを使用していないことを検討してください。ディスクベースのストリームを使用した場合、メモリ圧が大幅に低下します。

0

xmlライターのバックストアとしてpackgPart.GetStream()のストリームを使用してください。

また、メモリ内にCSV全体をロードする必要はありません。

ここではストリームのみを使用しているバージョンです。

void Main() 
{ 
    string inputFile = "D:\\_bigfile.csv"; 
    string path = "D:\\pack.zip"; 


    Package package = null; 
    using (package = ZipPackage.Open(path, FileMode.Create)) 
    { 

     var packgPart = package.CreatePart(new Uri("/test.xml", UriKind.Relative), System.Net.Mime.MediaTypeNames.Text.Xml, CompressionOption.Maximum); 
     using (var inputStream = File.OpenRead(inputFile)) 
     { 
      CreateOpenXMLComWorkSheet_XMLWriter(inputStream, "", packgPart.GetStream()); 
     } 
    } 
} 
private const string univDelimiter = "|"; 

private static void CreateOpenXMLComWorkSheet_XMLWriter(Stream inputStream, string sheet, Stream packagePartStream) 

{ 
    string cellValue = ""; 
    string dataType = ""; 
    double dVal = 0; 
    string[] cols; 

    XmlWriterSettings xmlWriterSettings = new XmlWriterSettings(); 
    xmlWriterSettings.NewLineHandling = NewLineHandling.None; 
    xmlWriterSettings.Indent = false; 


    string nameSpace = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; 
    using (var xmlWriter = XmlWriter.Create(packagePartStream, xmlWriterSettings)) 
    { 
     xmlWriter.WriteStartElement("x","worksheet",nameSpace); 
     xmlWriter.WriteStartElement("x","sheetData",nameSpace); 

     using (var sr = new StreamReader(inputStream)) 
     { 
      string line = null; 
      while ((line = sr.ReadLine()) != null) 
      { 
       xmlWriter.WriteStartElement("x","row",nameSpace); 

       cols = line.Split(new string[] { univDelimiter }, StringSplitOptions.None); 
       for (int i = 1; i <= cols.Length; i++) 
       { 
        cellValue = cols[i - 1]; 
        if (double.TryParse(cellValue,out dVal)) 
        { 
         dataType = "n"; 
        } 
        else 
        { 
         dataType = "str"; 
        } 
        xmlWriter.WriteStartElement("x","c",nameSpace); 
        xmlWriter.WriteAttributeString("s", "13"); 
        xmlWriter.WriteAttributeString("t", dataType); 
        xmlWriter.WriteStartElement("x", "v",nameSpace); 
        xmlWriter.WriteValue(cellValue); 
        xmlWriter.WriteEndElement(); 
        xmlWriter.WriteEndElement(); 
       } 

       xmlWriter.WriteEndElement(); 
      } 
     } 
     xmlWriter.WriteEndElement(); 
     xmlWriter.WriteEndElement(); 
    } 
} 
関連する問題