Различия в кодировке между использованием WebClient и WebRequest?

При получении случайного индекса испанской газеты я не получаю правильно диакритические знаки с помощью WebRequest, они дают этот странный символ: , при загрузке ответа с того же uri с использованием WebClient я получаю соответствующий ответ.

Почему такая дифференциация?

var client = new WebClient();
string html = client.DownloadString(endpoint);

vs

WebRequest request = WebRequest.Create(endpoint);
using (WebResponse response = request.GetResponse())
{
    Stream stream = response.GetResponseStream();
    StreamReader reader = new StreamReader(stream);
    string html = reader.ReadToEnd();
}

person bevacqua    schedule 26.01.2012    source источник
comment
Я предполагаю, но это, вероятно, потому, что WebClient.DownloadString просматривает заголовок content-type (например, text/html; charset=utf-16), чтобы сделать вывод о кодировке, но ваш метод WebRequest использует UTF8 (по умолчанию для StreamReader)   -  person spender    schedule 26.01.2012
comment
заголовок content-type в этом случае не указывает кодировку.   -  person bevacqua    schedule 26.01.2012
comment
@Нико. Затем он должен выполнить тесты для UTF-8, UTF-16LE, UTF-16BE и UTF-32 в соответствии с преамбулами (для обнаружения спецификаций и других контрольных сигналов) и, наконец, по умолчанию использовать устаревший набор символов по умолчанию, который происходит для совпадать с сайтом на вашем компьютере. Поскольку HTTP предполагает латиницу-1 (в конце концов, это было начало 90-х), было бы неплохо явно использовать это как ваш выбор, я не знаю.   -  person Jon Hanna    schedule 26.01.2012


Ответы (1)


Вы просто предполагаете, что объект находится в UTF-8 при создании вашего потокового считывателя без явной установки кодировки. Вы должны изучить CharacterSet класса HttpWebResponse (не представленного базовым классом WebResponse) и открыть StreamReader с соответствующей кодировкой.

В противном случае, если он читает что-то, отличное от UTF-8, как если бы это было UTF-8, он столкнется с последовательностями октетов, которые недопустимы в UTF-8, и ему придется заменить символ замены U + FFFD () как лучшее, что он может сделать.

WebClient делает примерно следующее: DownloadString — это метод более высокого уровня, где WebRequest и его производные классы позволяют вам перейти на более низкий уровень, он имеет единственный вызов для «отправить запрос GET на URI, изучить заголовки, чтобы увидеть, какое кодирование содержимого используется, если вам нужно распаковать или распаковать gzip, посмотреть, какая кодировка символов используется, настроить программу чтения текста с этой кодировкой и потоком, а затем вызвать ReadAll()". Применяются плюсы и минусы нормальных высокоуровневых инструкций с большими фрагментами по сравнению с низкоуровневыми инструкциями с малыми фрагментами.

person Jon Hanna    schedule 26.01.2012
comment
Кроме того, если вы хотите отразить, что конкретно WebClient изменяет StreamReader на StreamReader reader = new StreamReader(stream, System.Text.Encoding.Default) - person Chris Haas; 26.01.2012
comment
@ChrisHaas Нет, это было бы еще хуже - хотя в этом случае это могло бы сработать - в том смысле, что оно будет работать для одной устаревшей кодировки, но не для UTF-8. Он проверяет заголовок и устанавливает правильный, который может совпадать с System.Text.Encoding.Default, но вполне вероятно, что это не так. Если заголовки явно не запрашивают кодировку, он пробует UTF-8, UTF-16LE, UTF-16BE и UTF-32 по порядку, проверяя, имеет ли результат какой-либо смысл. Наконец, если это не удается, он использует собственное свойство Encoding. - person Jon Hanna; 26.01.2012
comment
@ChrisHaas Конечно, если он не находит спецификацию или нулевой октет, который выдает игру, и не имеет явно установленного Encoding, это приведет к использованию System.Text.Encoding.Default. - person Jon Hanna; 26.01.2012
comment
Я просто говорю, как отразить то, что делает WebClient, а не то, что это хорошо или плохо. Документы говорят, что WebClient использует System.Text.Encoding.Default по умолчанию. Лично я обычно проверяю сами необработанные байты при работе с сайтами, находящимися вне моего контроля, и возвращаюсь к заголовкам, если не могу понять это. - person Chris Haas; 26.01.2012
comment
@ChrisHaas Я вижу, что вы правы, документы говорят об этом. Однако код лучше, чем говорится в документах, если вы посмотрите в ILSpy или Reflector. Сначала он проверяет заголовок Content-Type и пытается получить из него кодировку, затем выполняет некоторые тесты для спецификаций, а затем использует свое свойство Encoding (которое по умолчанию равно System.Text.Encoding.Default) в качестве крайней меры. - person Jon Hanna; 26.01.2012