Как десериализовать только часть XML-документа в C#

Неустранимая ошибка: допустимый размер памяти из XXX байт исчерпан (пытался выделить XXX байты)

Недостаточно памяти для запуска вашего скрипта. PHP достиг предела памяти и перестает его выполнять. Эта ошибка является фатальной, сценарий останавливается. Значение предела памяти можно настроить либо в файле php.ini, либо с помощью ini_set('memory_limit', '128 M'); в скрипте (который перезапишет значение, определенное в php.ini). Цель ограничения памяти заключается в том, чтобы не допустить, чтобы один скрипт PHP собирал всю доступную память и приводил к остановке всего веб-сервера.

Первое, что нужно сделать, это свести к минимуму объем памяти, необходимый вашему сценарию , Например, если вы читаете большой файл в переменной или извлекаете много записей из базы данных и сохраняете их все в массиве, которые могут использовать много памяти. Измените свой код, чтобы вместо этого читать строки по строке или извлекать записи базы данных по одному, не сохраняя их все в памяти. Это требует немного концептуального понимания того, что происходит за кулисами, и когда данные хранятся в памяти и в других местах.

Если эта ошибка возникла, когда ваш сценарий не выполнял интенсивную работу с памятью, вы вам нужно проверить свой код, чтобы узнать, есть ли утечка памяти. Функция memory_get_usage является вашим другом.

Вопросы, относящиеся:

27
задан Community 23 May 2017 в 12:32
поделиться

8 ответов

Это может быть немного старая тема, но я все равно опубликую ее. У меня была такая же проблема (нужно было десериализовать, например, 10 КБ данных из файла, размер которого превышает 1 МБ). В основном объекте (у которого есть InnerObject, который должен быть десериализатором) я реализовал интерфейс IXmlSerializable, а затем изменил метод ReadXml.

В качестве входных данных используется xmlTextReader, первая строка предназначена для чтения до тега XML:

reader.ReadToDescendant("InnerObjectTag"); //tag which matches the InnerObject

Затем создайте XMLSerializer для типа объекта, который мы хотим десериализовать, и десериализовать его

XmlSerializer   serializer = new XmlSerializer(typeof(InnerObject));

this.innerObject = serializer.Deserialize(reader.ReadSubtree()); //this gives serializer the part of XML that is for  the innerObject data

reader.close(); //now skip the rest 

это сэкономило мне много времени, чтобы десериализовать и позволяет мне читать только часть XML (только некоторые детали, описывающие файл, которые могут помочь пользователю решить, является ли файл тем, что он хочет загрузить).

39
ответ дан 28 November 2019 в 05:03
поделиться

Можно управлять, как сериализация сделана путем реализации интерфейса ISerializable в классе. Обратите внимание, что это будет также подразумевать конструктора с сигнатурой метода (информация о SerializationInfo, контекст StreamingContext) и уверенный, что можно сделать то, что Вы спрашиваете с этим.

Однако внимательно рассмотрели в том, необходимо ли действительно сделать это с потоковой передачей, потому что, если Вы не должны использовать механизм потоковой передачи, достигая того же самого с Linq к XML, будет легче, и, более простым поддержать в долгосрочной перспективе (IMO)

3
ответ дан Tim Jarvis 28 November 2019 в 05:03
поделиться

Я думаю, что предыдущий комментатор корректен в своем комментарии, что XML не мог бы быть лучшим выбором запоминающего устройства здесь.

, Если Вы имеете проблемы масштаба и не используете в своих интересах некоторые из других тонкостей, Вы добираетесь с XML, как преобразования, Вы могли бы быть более обеспеченным использованием базы данных для Ваших данных. Операции, которые Вы делаете действительно, кажется, вписываются больше в ту модель.

я знаю, что это действительно не отвечает на Ваш вопрос, но я думал, что выделю альтернативное решение, которое Вы могли бы использовать. Хорошая база данных и соответствующее ИЛИ картопостроитель как .netTiers, NHibernate, или позже LINQ к SQL / Платформа Объекта, вероятно, вернули бы Вас и работающий с минимальными изменениями в остальной части Вашей кодовой базы.

2
ответ дан Anderson Imes 28 November 2019 в 05:03
поделиться

Обычно десериализация XML является бескомпромиссным суждением из поля, таким образом, необходимо будет, вероятно, настроить. Если Вы не делаете полной десериализации, Вы выполняете риск, что xml уродлив в элементе SalesPerson, и таким образом, документ недопустим.

, Если Вы готовы признать, что риск, Вы, вероятно, захотите сделать некоторый основной текстовый парсинг для вспыхивания элементов SalesPerson в различный документ с помощью средств для обработки простого текста, затем обрабатывают XML.

Это - хороший пример того, почему XML является не всегда корректным ответом.

1
ответ дан MikeD 28 November 2019 в 05:03
поделиться

Можно управлять тем, что части Автомобильного класса десериализовываются путем реализации интерфейс IXmlSerializable на Автомобильном классе, и затем в ReadXml (XmlReader) метод Вы считали бы и десериализовали бы Автомобильные элементы, но когда Вы достигаете элемента SalesPerson, Вы считали бы его поддерево как строку и затем создали бы Поток по текстовое содержание с помощью StreamWriter.

, Если Вы никогда не хотите, чтобы XmlSerializer выписал элемент SalesPerson, используйте [XmlIgnore] атрибут. Я не уверен, что Вы хотите произойти когда Вы seriailize Автомобильный класс к его представлению XML. Вы пытаетесь только предотвратить десериализацию SalesPerson в то время как все еще способность сериализировать представление XML SalesPerson, представленного Потоком?

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

0
ответ дан Oppositional 28 November 2019 в 05:03
поделиться

Попробуйте определить свойство SalesPerson как тип XmlElement . Это работает для вывода из веб-служб ASMX, которые используют сериализацию XML. Я думаю, это сработает и для ввода. Я ожидаю, что весь элемент окажется в XmlElement .

1
ответ дан 28 November 2019 в 05:03
поделиться

Если все, что вам нужно сделать, это проанализировать элемент SalesPerson, но сохранить его как строку, вам следует использовать преобразование Xsl, а не «десериализацию». Если, с другой стороны, вы хотите проанализировать элемент SalesPerson и заполнить объект в памяти только из всех других элементов, не относящихся к SalesPerson, то Xsl Transform также может быть подходящим вариантом. Если файлы слишком большие, вы можете разделить их и использовать Xsl для объединения разных XML-файлов, чтобы операции ввода-вывода SalesPerson выполнялись только тогда, когда вам это нужно.

0
ответ дан 28 November 2019 в 05:03
поделиться

Я бы посоветовал вам вручную читать из Xml, используя любые легкие методы, такие как XmlReader, XPathDocument или LINQ-to-XML .

Когда вам нужно прочитать только 3 свойства, я полагаю, вы можете написать код, который вручную считывает с этого узла и имеет полный контроль над тем, как он выполняется, вместо того, чтобы полагаться на сериализацию / десериализацию

0
ответ дан 28 November 2019 в 05:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: