2015-01-07 2 views
1

Я пытаюсь сериализовать XML-файл, и я столкнулся с некоторой проблемой. Посмотрите ниже в моем файле примера xml:xmlreader читает каждый второй шаг

<Information xmlns="dis"> 
    <SOS.Alert> 
    <signal>4</signal> 
    <tresh>RTX</tresh> 
    <obb>GGHUI</obb> 
    </SOS.Alert> 
    <SOS.Alert> 
    <signal>3</signal> 
    <tresh>RTR</tresh> 
    <obb>GGH</obb> 
    </SOS.Alert> 
    <SOS.Alert> 
    <signal>20</signal> 
    <tresh>WWRTX</tresh> 
    <obb>BBHUI</obb> 
    </SOS.Alert> 
    <SOS.Alert> 
    <signal>13</signal> 
    <tresh>DRTR</tresh> 
    <obb>GFH</obb> 
    </SOS.Alert> 
    .... 
</Information> 

Проблема в том, что она пропускает каждую секунду. Так что, если мы имеем 4 входа, как и выше будет сериализовать только два:

<SOS.Alert> 
<signal>4</signal> 
<tresh>RTX</tresh> 
<obb>GGHUI</obb> 
</SOS.Alert> 
<SOS.Alert> 
<signal>20</signal> 
<tresh>WWRTX</tresh> 
<obb>BBHUI</obb> 
</SOS.Alert> 

Это код, я использую:

Me.xmlreader = New XmlTextReader(inputFileName) 


      Me.xmlreader.WhitespaceHandling = WhitespaceHandling.None 
      While (Me.xmlreader.Read()) 
       If ((Me.xmlreader.Name = "SOS.Alert") And (Me.xmlreader.NodeType = XmlNodeType.Element) And (Me.xmlreader.IsStartElement())) Then 

        Me.data.MyList.Add(xmlreader.ReadOuterXml) 
       End If 

      End While 

Обратите внимание, что я хочу остаться с XMLTeamReader, потому что я действую на большой XML-файл размером более 1,5 ГБ, а XDocument, XElement и другие не рассматриваются, поскольку они загружают весь XML в память, поэтому исключение OutoOfMemory.

ответ

1

Я считаю, что проблема заключается в вызове ReadOuterXml. Посмотрите на эту статью MSDN, в частности таблицы Замечания, которая показывает «Позиция после вызова»: http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.readouterxml%28v=vs.110%29.aspx

Это показывает, что с этим XML:

<item1>text1</item1><item2>text2</item2> 

Если вы звоните ReadOuterXml в то время как в ITEM1, это будет переместите читателя вперед в Item2. Поскольку это происходит в цикле, ваш читатель снова продвинется вперед и пройдет мимо стартового тега ко второму пункту. Это заставит вас «пропустить»

0

После ReadOuterXml читатель уже расположен на следующем желаемом узле, второй SOS.Alert. Но из-за вызова Me.xmlreader.Read(), следующий элемент в xml читается, signal. Это слишком далеко. Теперь вы читаете узлы, вы видите третий SOS.Alert. Мне кажется, вам нужен код ниже. Найдя свой первый SOS.Alert, он продолжит читать ветки SOS.Alert до конца.

 Me.xmlreader = New XmlTextReader(inputFileName) 
     Me.xmlreader.WhitespaceHandling = WhitespaceHandling.None 
     While (Me.xmlreader.Read()) 
      If ((Me.xmlreader.Name = "SOS.Alert") And (Me.xmlreader.NodeType = XmlNodeType.Element) And (Me.xmlreader.IsStartElement())) Then 
       While ((Me.xmlreader.Name = "SOS.Alert") And (Me.xmlreader.NodeType = XmlNodeType.Element) And (Me.xmlreader.IsStartElement())) 
        Me.data.MyList.Add(xmlreader.ReadOuterXml) 
       End While 
      End If 
     End While 
+0

Использование моего старого кода завершает (конечно же, второй шаг) на 221155-й строке. Я внедрил ваш код, и через некоторое время я получил это исключение: «В mscorlib.dl произошло необработанное исключение типа« System.OutOfMemoryException ». Во всяком случае, я проверил первые пары строк, и кажется, что он принимает каждую строку. Как избежать этой ошибки? – unknown

+0

Вы читаете более 1,5 ГБ данных и сохраняете их в 'data' (' Me.data.MyList.Add'). Возможно, MyList не сможет справиться с этим. Помните, что при использовании старого кода ваш список будет содержать половину того, что он содержит, используя новый код. Возможно, вы можете изменить свою программу таким образом, чтобы вы обрабатывали результат непосредственно перед его хранением в списке; в этом случае вам не нужно столько памяти. Вы можете использовать профилировщик памяти, какой объект (ы) несет/несет ответственность за чрезмерную загрузку памяти. Если у вас его нет: есть пробные версии. Затем попробуйте исправить (или попросить о помощи еще раз). – Sjips

+0

С размером файла, который вы используете, вы, вероятно, проблема с большой кучей объектов (LOH). Эта часть кучи собирается GC, но не дефрагментирована. Во время добавления элементов в список емкость увеличивается за счет выделения новой памяти с двойным пространством, а массив/список копируется. Решением для этого является предварительное выделение ожидаемого количества элементов в конструкторе списка ('Dim list As New List (Of String) (1000000)'). Вам может потребоваться более высокая емкость, но помните, что массивы (а списки - массивы) не могут выходить за пределы 2 ГБ, даже на x64 (.Net4.5 имеет решение). – Sjips

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