C #: как прочитать строку из потока, а затем начать читать ее с начала? - PullRequest
3 голосов
/ 09 августа 2011

Мне нужно прочитать первую строку из потока, чтобы определить кодировку файла, а затем заново создать поток с этой кодировкой

Следующий код работает неправильно:

var r = response.GetResponseStream();
var sr = new StreamReader(r);
string firstLine =  sr.ReadLine();
string encoding = GetEncodingFromFirstLine(firstLine);
string text = new StreamReader(r, Encoding.GetEncoding(encoding)).ReadToEnd();

Текстовая переменная не содержит весь текст. По какой-то причине первая строка и несколько строк после нее пропущены.

Я попробовал все: закрытие StreamReader, сброс его, вызов отдельного GetResponseStream ... но ничего не получалось.

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

Обновление

Вот как выглядит GetEncodingFromFirstLine ():

public static string GetEncodingFromFirstLine(string line)
{
    int encodingIndex = line.IndexOf("encoding=");
    if (encodingIndex == -1)
    {
        return "utf-8";
    }
    return line.Substring(encodingIndex + "encoding=".Length).Replace("\"", "").Replace("'", "").Replace("?", "").Replace(">", "");
}

...

// true
Assert.AreEqual("windows-1251", GetEncodingFromFirstLine(@"<?xml version=""1.0"" encoding=""windows-1251""?>")); 

** Обновление 2 **

Я работаю с файлами XML, и текстовая переменная анализируется как XML:

var feedItems = XElement.Parse(text);

Ответы [ 3 ]

6 голосов
/ 09 августа 2011

Что ж, вы просите его определить кодировку ... и для этого требуется прочитать данные. Это читает его из базового потока, и затем вы создаете еще один StreamReader вокруг того же потока.

Я предлагаю вам:

  • Получить поток ответов
  • Получить все данные в байтовом массиве (или MemoryStream)
  • Определить кодировку (которая должна выполняться для байтов , а не текста - в настоящее время вы уже предполагаете UTF-8 , создав StreamReader)
  • Создайте MemoryStream вокруг байтового массива и StreamReader вокруг этого

Непонятно, что делает ваш метод GetEncodingFromFirstLine ... или что это за файл на самом деле. Дополнительная информация может помочь вам помочь.

РЕДАКТИРОВАТЬ: Если это для загрузки некоторого XML, не изобретайте колесо. Просто передайте поток одному из существующих классов синтаксического анализа XML, который выполнит соответствующее обнаружение для вас.

2 голосов
/ 09 августа 2011

Вам необходимо изменить текущую позицию в потоке на начало.

r.Position = 0;
string text = new StreamReader(r, Encoding.GetEncoding(encoding)).ReadToEnd();
1 голос
/ 09 августа 2011

Я нашел ответ на свой вопрос здесь:

Как я могу прочитать поток ответов Http дважды в C #?

Stream responseStream = CopyAndClose(resp.GetResponseStream());
// Do something with the stream
responseStream.Position = 0;
// Do something with the stream again


private static Stream CopyAndClose(Stream inputStream)
{
const int readSize = 256;
byte[] buffer = new byte[readSize];
MemoryStream ms = new MemoryStream();

int count = inputStream.Read(buffer, 0, readSize);
while (count > 0)
{
    ms.Write(buffer, 0, count);
    count = inputStream.Read(buffer, 0, readSize);
}
ms.Position = 0;
inputStream.Close();
return ms;
}
...