StringBuilder для конкатенации строк создает исключение OutOfMemoryException

Решение:

Я смог решить проблему! Вот окончательный код:

XmlDocument xmldoc = new XmlDocument();
XmlReaderSettings settings = new XmlReaderSettings { NameTable = new NameTable() };
XmlNamespaceManager xmlns = new XmlNamespaceManager(settings.NameTable);
xmlns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
XmlParserContext context = new XmlParserContext(null, xmlns, "", XmlSpace.Default);
XmlReader reader = XmlReader.Create(strXmlFile, settings, context);
xmldoc.Load(reader);

Также еще один совет при поиске по узлам не забудьте установить правильное пространство имен, например, для поиска метки метки выше, это будет формат:

// Setup default namespace manager for searching through nodes
XmlNamespaceManager manager = new XmlNamespaceManager(xmldoc.NameTable);
string defaultns = xmldoc.DocumentElement.GetNamespaceOfPrefix("");
manager.AddNamespace("ns", defaultns);

// get a list of all <Placemark> nodes
XmlNodeList listOfPlacemark = xmldoc.SelectNodes("//ns:Placemark", manager);

// iterate over the <Placemark> nodes
foreach (XmlNode singlePlaceMark in listOfPlacemark)

// Get the description subnode
XmlNode descriptionNode = singlePlaceMark.SelectSingleNode("ns:description", manager);

..
15
задан Community 23 May 2017 в 11:46
поделиться

6 ответов

Строка underyling, которую Вы создаете, будет также нуждаться в непрерывном блоке памяти, потому что это представлено как массив символов (массивы требуют непрерывной памяти). Если StringBuilder выдает исключение OOM Вы, woludn't могут создать базовое без него.

Если создание строки вызывает OOM, там вероятно более серьезная проблема в Вашем приложении.

Редактирование в ответ на разъяснение:

Существует небольшое подмножество случаев, где создание строки с StringBuilder перестанет работать, когда ручная конкатенация успешно выполнится. Ручная конкатенация будет использовать точную длину, требуемую для объединения двух строк, в то время как StringBuilder имеет другой algorithmn для выделения памяти. Это более агрессивно и вероятно выделит больше памяти, чем на самом деле необходимо для строки.

Используя StringBuilder также приведет к временному удвоению памяти, требуемой, так как строка будет присутствовать в Системе. Строковая форма и StringBuilder одновременно в течение короткого времени.

Но если один путь вызывает OOM, и другой не, это все еще вероятные точки к более серьезной проблеме в Вашей программе.

19
ответ дан 1 December 2019 в 02:02
поделиться

Если StringBuilder собирается бросить OutOfMemoryException в Вашу конкретную ситуацию, то выполнение ручной конкатенации строк НЕ является лучшим решением; это намного хуже. Это точно имеет место (создание чрезвычайно, чрезвычайно длинная строка), где StringBuilder, как предполагается, используется. Ручная конкатенация строки, это большое будет много раз брать память, которую взяло бы создание строки с StringBuilder.

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

4
ответ дан 1 December 2019 в 02:02
поделиться

О каком количестве памяти мы говорим? Я не говорю о свободной памяти или общей памяти в системе, но какой длины строка, Вы конкатенируете?

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

В той точке необходимо действительно реструктурировать код.

Например, вот различные способы сражаться с проблемой:

  1. Не сохраняйте столько же данных в памяти когда-то, выражайтесь на диске или чем-то
  2. Разбейте его, сохраните список string/stringbuilders и только добавьте к ним до определенной длины прежде, чем переключиться на новую, держит "непрерывную память в страхе" проблема
  3. Реструктурируйте алгоритм для не создания гигабайта данных в памяти вообще
3
ответ дан 1 December 2019 в 02:02
поделиться

Если Вы смотрите на как StringBuilder реализован, Вы будете видеть, что это на самом деле использует a String содержать данные (String имеет внутренние методы, которые позволят StringBuilder изменить на месте).

Т.е. они оба используют тот же объем памяти. Однако с тех пор StringBuilder автоматически расширит основной массив и скопирует по мере необходимости при необходимости (но удвоение способности), который наиболее вероятен причина из ошибки памяти. Но поскольку другие уже указали на оба из требования непрерывного блока памяти,

2
ответ дан 1 December 2019 в 02:02
поделиться

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

Это проблемы влияет даже на Систему. Строковый класс, таким образом, необходимо скорее разделить вход на блоки в Список <строка> и обработать данные параллельно, которые должны увеличить общую производительность, если записано правильно.

1
ответ дан 1 December 2019 в 02:02
поделиться

При выполнении soclose к пределам памяти, что это - даже беспокойство, то необходимо, вероятно, думать о другой архитектуре или получить более раскормленную машину.

2
ответ дан 1 December 2019 в 02:02
поделиться
Другие вопросы по тегам:

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