2015-05-07 2 views
0

В принципе, я хочу извлечь поток из XmlReader и напрямую base64 декодировать его в файл.Чтение потока из XmlReader, base64 его декодировать и записать результат в файл

Структура XML-файла видна here. Чтобы получить значение, я должен использовать ReadInnerXml(). Можно ли вместо этого использовать ReadValueChunk?

Вот мой текущий код:

using (XmlReader reader = XmlReader.Create("/your/path/47311.xml")) 
{ 
    while(reader.Read()) 
    { 
     if (reader.IsStartElement() && reader.NodeType == XmlNodeType.Element) { 
      switch (reader.Name) { 
      case "ttOutputRow": 
       reader.ReadToDescendant ("cKey"); 
       switch (reader.ReadInnerXml()) { 
       case "findMe": 
        reader.ReadToNextSibling ("cValue"); 
        // here begins the interesting part 
        char[] buffer = new char[4096]; 
        int charRead; 
        using (var destStream = File.OpenWrite ("/your/path/47311.jpg")) { 
         while ((charRead = reader.ReadValueChunk (buffer, 0, 4096)) != 0) { 
          byte[] decodedStream = System.Convert.FromBase64String (new string (buffer)); 
          await destStream.WriteAsync(decodedStream, 0, decodedStream.Length); 
          Console.WriteLine ("in"); 
         } 

        } 
        break; 
       default: 
        break; 
       } 
       break; 
      default: 
       break; 
      } 
     } 
    } 
} 

В настоящее время он не читает значение в

не Могу ли я использовать ReadValueChunk для этого.? Как я могу напрямую использовать поток из XmlReader, не жертвуя слишком большим количеством памяти?

Edit:

По dbc я изменил мой код. Это то, что я в настоящее время использую:

using (XmlReader reader = XmlReader.Create("test.xml")) 
{ 
    while(reader.Read()) 
    { 
     if (reader.IsStartElement() && reader.NodeType == XmlNodeType.Element) { 
      switch (reader.Name) { 
      case "ttOutputRow": 
       reader.ReadToDescendant ("cKey"); 
       switch (reader.ReadInnerXml()) { 
       case "findMe": 
        reader.ReadToNextSibling ("cValue"); 
        byte[] buffer = new byte[40960]; 
        int readBytes = 0; 
        using (FileStream outputFile = File.OpenWrite ("test.jpg")) 
        using (BinaryWriter bw = new BinaryWriter(outputFile)) 
        { 
         while ((readBytes = reader.ReadElementContentAsBase64(buffer, 0, 40960)) > 0) { 
          bw.Write (buffer, 0, readBytes); 
          Console.WriteLine ("in"); 
         } 

        } 
        break; 
       default: 
        break; 
       } 
       break; 
      default: 
       break; 
      } 
     } 
    } 
} 

Here вы можете найти тестовый файл. Реальный файл немного больше и поэтому занимает гораздо больше времени.

Приведенный выше код не работает должным образом. Это очень медленно, и извлеченное изображение в основном черное (уничтожено).

+0

Я просто попробовал обновленный код в тестовом файле, который вы предоставили, и он отлично работает. Изображение какого-то парня, занимающегося серфингом. Чтобы проверить производительность, убедитесь, что вы работаете за пределами визуальной студии в сборке релизов. Кроме того, записи на консоль могут быть очень медленными. – dbc

+0

Это интересно. Я использую Xamarin Studio на Mac для своего приложения, и здесь изображение неправильно декодировано.Почему он не работает для меня? Я могу загрузить вам проблемный образ, если вы мне не верите. Я попробую это, не введев что-то на консоль в следующий раз (но в настоящее время я работаю над другим проектом). Но производительность не должна быть такой плохой в конфигурации отладки. Я буду держать вас в курсе. – testing

+1

Теперь я попробовал его с консольным проектом, и здесь он был намного быстрее, но изображение все еще повреждено. Я спрашиваю коллегу, и тот же код работает для него (он использует Xamarin Studio в Windows). Кажется, это ошибка. – testing

ответ

1

Чтобы дать окончательный ответ на ваш вопрос, мне нужно будет увидеть XML, который вы пытаетесь прочитать. Тем не менее, две точки:

  1. В соответствии с documentation для Convert.FromBase64String:

    Метод FromBase64String предназначен для обработки одной строки, которая содержит все данные, которые должны быть декодированы. Чтобы декодировать базовые 64-символьные данные из потока, используйте класс System.Security.Cryptography.FromBase64Transform.

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

  2. Вы можете использовать XmlReader.ReadElementContentAsBase64 или XmlReader.ReadElementContentAsBase64Async именно для этой цели. Из документов:

    Этот метод считывает содержимое элемента, декодирует его, используя кодирование Base64 и возвращает декодированные двоичные байты (например, встроенный в кодировке Base64 GIF изображение) в буфер.

    Фактически, пример в документации демонстрирует, как извлечь изображение с кодировкой base64 из файла XML и записать его в двоичный файл в виде кусков.

+0

Теперь я попытался использовать 'ReadElementContentAsBase64'. Эта функция кажется очень медленной. Неважно, какой размер буфера я выбираю (чем больше, тем быстрее, но все же слишком медленно). Изображение неправильно декодировано. Я вижу начало изображения, но остальное (основная часть изображения) остается черным. Я обновил свой вопрос, включая тестовый файл. Я также попробовал код 1: 1 из примера, но результат остается тем же. – testing

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