Преобразовать XDocument в массив байтов (и массив байтов в XDocument)

#c# #xml #linq-to-xml #bytearray

#c# #xml #linq-to-xml #массивы

Вопрос:

Я перенял систему, которая хранит большие XML-документы в SQL Server в двоичном формате.

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

Класс Entity Framework, содержащий XML, был расширен, так что двоичные данные доступны в виде строки, подобной этой:

 partial class XmlData
{
    public string XmlString { get { return Encoding.UTF8.GetString(XmlBinary); } set { XmlBinary = Encoding.UTF8.GetBytes(value); } }
}
  

Я хочу еще больше расширить класс, чтобы он выглядел примерно так:

 partial class XmlData
{
    public string XmlString{ get { return Encoding.UTF8.GetString(XmlBinary); } set { XmlBinary = Encoding.UTF8.GetBytes(value); } }

    public XDocument XDoc
    {
        get
        {
            // Convert XmlBinary to XDocument
        }
        set
        {
            // Convert XDocument to XmlBinary
        }
    }
}
  

Я думаю, что я почти разобрался с преобразованием, но когда я использую метод частичных классов XmlString для получения XML обратно из БД, XML всегда обрезается ближе к концу, всегда с другим количеством символов:

 var memoryStream = new MemoryStream();
var xmlWriter = XmlWriter.Create(memoryStream);
myXDocument.WriteTo(xmlWriter);
XmlData.XmlBinary = memoryStream.ToArray();
  

РЕШЕНИЕ

Вот основное преобразование:

 var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Encoding = Encoding.UTF8 };
using (var memoryStream = new MemoryStream())
using (var xmlWriter = XmlWriter.Create(memoryStream, settings))
{
    myXDocument.WriteTo(xmlWriter);
    xmlWriter.Flush();
    XmlData.XmlBinary = memoryStream.ToArray();
}
  

Но по какой-то причине в этом процессе в XML добавляются некоторые странные символы, отличные от ascii, поэтому использование моего предыдущего метода XmlString загрузит эти странные символы и XDocument.Parse() сломается, поэтому мой новый частичный класс выглядит так:

 partial class XmlData
{
    public string XmlString 
    { 
        get 
        {
            var xml = Encoding.UTF8.GetString(XmlBinary);
            xml = Regex.Replace(xml, @"[^u0000-u007F]", string.Empty); // Removes non ascii characters
            return xml;
        } 
        set 
        { 
            value = Regex.Replace(value, @"[^u0000-u007F]", string.Empty); // Removes non ascii characters
            XmlBinary = Encoding.UTF8.GetBytes(value); 
        } 
    }

    public XDocument XDoc
    {
        get
        {
            using (var memoryStream = new MemoryStream(XmlBinary))
            using (var xmlReader = XmlReader.Create(memoryStream))
            {
                var xml = XDocument.Load(xmlReader);
                return xml;
            }
        }
        set
        {
            var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Encoding = Encoding.UTF8 };
            using (var memoryStream = new MemoryStream())
            using (var xmlWriter = XmlWriter.Create(memoryStream, settings))
            {
                value.WriteTo(xmlWriter);
                xmlWriter.Flush();
                XmlBinary = memoryStream.ToArray();
            }
        }
    }
}
  

Комментарии:

1. Похоже, что буфер одного из потоков / записей не был очищен во время чтения или записи — используйте using (...) для автоматического закрытия, очистки и удаления, а также проверьте, что во всех местах, где вы закончили чтение / запись, вы сделали .Flush()

2. Вот и все! Продолжайте и добавьте ответ, и я его приму.

Ответ №1:

Похоже, что буфер одного из потоков / записей не был очищен во время чтения или записи — используйте using (...) для автоматического закрытия, очистки и удаления, а также проверьте, что во всех местах, где вы закончили чтение / запись, вы сделали .Flush()