Кодирование с помощью HttpClient в .NET 4.5

Я использую некоторые данные, используя fogbugz XML API . Этот API всегда предлагает данные в формате UTF-8.

При использовании класса WebClient для выполнения запроса я могу установить кодировку. Например:

var result = new WebClient(); 
result.Encoding = Encoding.UTF8;

А как же класс HttpClient?

HttpClient client = new HttpClient();

Должен ли я использовать:

client.GetByteArrayAsync(url);

... а затем преобразовать байты из кодировки (UTF-8) в строку?

Или есть способ напрямую получить содержимое в виде строки UTF-8?

using (var client = Connector.GetHttpClient())
{
    var byteData = await client.GetByteArrayAsync(url);
    data = Encoding.UTF8.GetString(byteData);
}

Наконец, вот выдержка из ответа XML:

<?xml version="1.0" encoding="UTF-8"?>
<response>

person Boas Enkler    schedule 13.06.2012    source источник


Ответы (2)


Вы должны иметь возможность использовать GetStringAsync — я ожидаю, что кодировка будет определяться заголовками в ответе HTTP. Если сервер не указывает кодировку, вам следует попросить ее исправить.

В качестве альтернативы, если вы извлекаете XML-данные, просто извлеките их как массив байтов и проанализируйте этот двоичный файл напрямую - объявление XML должно в любом случае указывать кодировку для данных, отличных от UTF-8/UTF-16, поэтому я бы сказал, что на самом деле так меньше места для ошибки.

person Jon Skeet    schedule 13.06.2012
comment
Привет, Джон. Спасибо за ваш ответ. Тег кодирования всегда включается в ответ. В случае с FogBugz он определяется как всегда UTF-8. Вот пример начала XML ‹?xml version=1.0 encoding=UTF-8?› ‹response›.... Я полагался на это с веб-клиентом, там кодировка не учитывалась API, так что я не не уверен, что снова доверяю API без документированной функции :-( Итак, получение ByteArray (как мой пример кода выше) должно быть самым безопасным способом? - person Boas Enkler; 13.06.2012
comment
@BoasEnkler: клиент не собирается брать кодировку из body — она должна быть указана в заголовках. Но, как я уже сказал, более безопасный способ — получить его в виде байтов и проанализировать только из двоичных данных. (Создайте MemoryStream, чтобы обернуть массив байтов.) - person Jon Skeet; 13.06.2012
comment
хорошо, думаю, это лучшее решение. Крис также рекомендовал то же самое :) - person Boas Enkler; 13.06.2012
comment
Еще один вопрос. При переносе байтов в память и передаче их в XELement.Load. Удаляет ли этот метод поток памяти автоматически, когда он больше не нужен? Или я должен позаботиться об этом сам? - person Boas Enkler; 13.06.2012
comment
Теоретически вы должны его утилизировать. На практике Dispose ничего не делает для MemoryStream (за ним нет неуправляемых ресурсов). - person Kris Vandermotten; 13.06.2012
comment
Могу ли я избавиться от него сразу после загрузки, если он существует, пока я использую созданный XElement? - person Boas Enkler; 13.06.2012
comment
@BoasEnkler: В основном то, что сказал Крис. Вы можете избавиться от него сразу после того, как вы проанализировали данные из него, если вы просто используете XElement.Parse. Если бы вы создали из него XmlReader, это было бы другое дело, поскольку он поддерживает ссылку на поток, поэтому он может считывать данные только по мере необходимости. - person Jon Skeet; 13.06.2012

Если я правильно понимаю, вам не нужна строка, вам нужен XML.

Итак, если ваши данные не слишком велики, прочитайте массив байтов с помощью

byte[] bytes = await client.GetByteArrayAsync(url); 

затем создайте поток памяти из этого массива, а затем прочитайте XML из этого потока, например:

XElement element = XElement.Load(new MemoryStream(bytes), LoadOptions.None);

Если вы используете другой XML API, вы можете использовать

XmlReader reader = XmlReader.Create(new MemoryStream(bytes));
person Kris Vandermotten    schedule 13.06.2012
comment
хорошая идея. но я также хотел бы понять ожидаемое поведение для других сценариев. - person Boas Enkler; 13.06.2012