2014-12-16 4 views
0

Я работаю над приложением, которое преобразует xml в другой xml с помощью xslt. Небольшие выборочные данные отлично работают, но когда он идет вживую, он показывает исключение типа System.OutOfMemoryException. Файл xml продукта имеет размер более 600 МБ. В диспетчере задач Windows он показывает, что авария происходит, когда использование памяти приложения превышает 1,6 ГБ. Я попытался увеличить размер физической памяти и виртуальной памяти. Это не помогает.Исключение типа 'System.OutOfMemoryException' было брошено в C#

Любые предложения?

C#:

// Create the XsltSettings object with document() enabled and script disabled. 
    XsltSettings xsltsettings = new XsltSettings(true, false); 
    XslCompiledTransform xslt = new XslCompiledTransform(); 
    xslt.Load(this.XsltFile, xsltsettings, new XmlUrlResolver()); 

    // Create the writer. 
    XmlWriterSettings settings = new XmlWriterSettings(); 
    settings.Indent = true; 
    settings.IndentChars = "\t"; 
    settings.OmitXmlDeclaration = true; 
    settings.ConformanceLevel = ConformanceLevel.Auto; 
    settings.CloseOutput = false; 

    TextWriter writer = new StreamWriter(OutFile.Replace(".xml", ".txt")); 
    XmlReader reader = XmlReader.Create(InFile); 
    reader.MoveToContent(); 
    // Execute the transformation. 
    xslt.Transform(reader, null, writer); 
    writer.Close(); 
    reader.Close(); 

XSLT:

<xsl:stylesheet version="1.0" 
       xmlns="http://www.ncr.com/rsd/WebOffice/ConfigurationManagement" 
       xmlns:acm="http://www.ncr.com/rsd/WebOffice/ConfigurationManagement" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
       exclude-result-prefixes="msxsl acm"> 
    <xsl:output method="text" indent="no"/> 

    <xsl:template match="/"> 
    <xsl:for-each select="/Data/Record"> 
     <xsl:variable name="desc"> 
     <xsl:call-template name="StringReplace"> 
      <xsl:with-param name="text" select="desc" /> 
      <xsl:with-param name="replace" select='"&apos;"' /> 
      <xsl:with-param name="by" select='"&apos;&apos;"' /> 
     </xsl:call-template> 
     </xsl:variable> 
     <xsl:variable name="startdate"> 
     <xsl:call-template name="NumberofDays"> 
      <xsl:with-param name="text" select="sale_start_date"/> 
     </xsl:call-template> 
     </xsl:variable> 
     <xsl:variable name="quotes">'</xsl:variable> 

     <xsl:value-of select="concat('(', 
     key, 
     ',', 
     $quotes, 
     normalize-space(substring($desc, 2, string-length($desc) - 2)), 
     $quotes, 
     ',',  
     sale_price div 100, 
     ',', 
     sale_deal, 
     ',', 
     $startdate, 
     ',', 
     sale_start_time, 
     ')')"/> 
     <xsl:choose> 
     <xsl:when test="position() = last()">;</xsl:when> 
     <xsl:otherwise>,</xsl:otherwise> 
     </xsl:choose> 
     <xsl:text>&#xa;</xsl:text> 
    </xsl:for-each> 
    </xsl:template> 

    <xsl:template name="StringReplace"> 
    <xsl:param name="text"/> 
    <xsl:param name="replace"/> 
    <xsl:param name="by"/> 
    <xsl:choose> 
     <xsl:when test="contains($text, $replace)"> 
     <xsl:value-of select="substring-before($text,$replace)"/> 
     <xsl:value-of select="$by"/> 
     <xsl:call-template name="StringReplace"> 
      <xsl:with-param name="text" select="substring-after($text,$replace)"/> 
      <xsl:with-param name="replace" select="$replace"/> 
      <xsl:with-param name="by" select="$by"/> 
     </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="$text"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

    <xsl:template name="NumberofDays"> 
    <xsl:param name="text"/> 
    <xsl:variable name= "year" select="floor($text div 10000)"/> 
    <xsl:variable name= "month" select="floor(($text mod 10000) div 100)"/> 
    <xsl:variable name= "day" select="floor(($text mod 10000) mod 100)"/> 

    <xsl:choose> 
     <xsl:when test="$month != 0 and $day !=0"> 
     <xsl:variable name= "yeardate"> 
      <xsl:call-template name="CalculateJulianDay"> 
      <xsl:with-param name="year" select="$year"/> 
      <xsl:with-param name="month" select="$month"/> 
      <xsl:with-param name="day" select="$day"/> 
      </xsl:call-template> 
     </xsl:variable> 
     <xsl:variable name= "startdate"> 
      <xsl:call-template name="CalculateJulianDay"> 
      <xsl:with-param name="year" select="$year"/> 
      <xsl:with-param name="month" select="1"/> 
      <xsl:with-param name="day" select="1"/> 
      </xsl:call-template> 
     </xsl:variable> 
     <xsl:value-of select="concat($year, format-number(number($yeardate)-number($startdate)+1,'000'))" ></xsl:value-of> 
     </xsl:when> 
     <xsl:otherwise>0000000</xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

    <xsl:template name="CalculateJulianDay"> 
    <xsl:param name="year"/> 
    <xsl:param name="month"/> 
    <xsl:param name="day"/> 

    <xsl:variable name="a" select="floor((14 - $month) div 12)"/> 
    <xsl:variable name="y" select="$year + 4800 - $a"/> 
    <xsl:variable name="m" select="$month + 12 * $a - 3"/> 

    <xsl:value-of select="$day + floor((153 * $m + 2) div 5) + $y * 365 + 
     floor($y div 4) - floor($y div 100) + floor($y div 400) - 
     32045"/> 
    </xsl:template> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

XML:

<?xml version="1.0" encoding="us-ascii"?> 
<Data> 
    <Record> 
     <key>00000000000017</key>  
     <desc>"P&amp;G FIXTURE"</desc>  
     <sale_price>120</sale_price> 
     <sale_deal>0</sale_deal> 
     <sale_start_date>20121002</sale_start_date> 
     <sale_start_time>0001</sale_start_time> 
    </Record> 
</Data> 
+0

Вы могли наблюдать память, используемую в диспетчере задач, вкладку производительности и посмотреть, как она будет –

+0

Что именно делает ваше преобразование? Этот фрагмент кода сам по себе ничего не говорит. Покажите нам свое преобразование и, возможно, образец данных, проблема в нем. –

+0

Ниже приведена не ваша проблема, если она сбой в первый раз, но ваши 'TextWriter' и' XmlReader' должны находиться в 'using' blocks:' using (TextWriter writer = new StreamWriter (...)) {using (XmlReader reader = XmlReader.Create (...)) {...}} '. –

ответ

0

Не зная точно, что ваш объект XSLT является, но предполагает, что это XslCompiledTransform. Вы видели это: MSDN Blog Article

0

Вы можете ударить 2Гб по размеру процесса 32-битной на 32-битной системой

Если вы перемещаете до 64-битной системы bu т продолжать использовать процесс 32bit, ваше приложение предельного размера будет 4Gb

На 64-битной системе с 64-битной процесса вы хорошо до 8ТБА или так

+0

Приложение было запущено на виртуальной машине, которая является стандартом Windows Server 2008 R2, 64-разрядной с ОЗУ 8 ГБ. Не уверен, почему ограничение 2GB все еще сохраняется. – potatolover

+0

вы проверили с диспетчером задач? Он быстро скажет вам размер приложения перед сбоем –

+0

в диспетчере задач, он показывает, что авария происходит с объемом памяти 1,6 ГБ. Приложение 32 бит. Почему максимальная память может достигать 4 ГБ? – potatolover

Смежные вопросы