2016-06-18 7 views
4

Я хочу определить кодировку XML-документа перед его разбором. Поэтому я нашел в стеке переполнение этот скрипт.C# EndOfStream всегда верно - поиск/позиция до 0 не работает

public static XElement GetXMLFromStream(Stream uploadStream) 
{ 
    /** Remember position */ 
    var position = uploadStream.Position; 

    /** Get encoding */ 
    var xmlReader = new XmlTextReader(uploadStream); 
    xmlReader.MoveToContent(); 

    /** Move to remembered position */ 
    uploadStream.Seek(position, SeekOrigin.Begin); // with "pos" = 0 it not works, too 
    uploadStream.Seek(position, SeekOrigin.Current); // if I remove this I have the same issue! 

    /** Read content with detected encoding */ 
    var streamReader = new StreamReader(uploadStream, xmlReader.Encoding); 
    var streamReaderString = streamReader.ReadToEnd(); 
    return XElement.Parse(streamReaderString); 
} 

Но это не сработает. Всегда получаю EndOfStreamtrue. Но это не !!!! -.-

Например, у меня есть строка <test></test>. Начало: 0, Конец: 13

Если I ReadToEnd или MoveToContent, то конец будет успешно выполнен. EndOfStream: true then.

Если сбросить положение 0 (например) с помощью Seek или Position затем через new StreamReader шоу всегда EndOfStream является истинным .

Дело в том, что поток uploadStream - это поток, который я не могу закрыть.

Это SharpZipLib поток потока передачи http. Поэтому я не могу закрыть этот поток. Я могу работать с ним.

И плохо то, только потому, что Position и Seek не работают ... Только потому, что ReadToEnd реле на этой Position. - Иначе это сработает. Я думаю!

Может быть, вы можете помочь моему в этой ситуации :-)

Большое спасибо заранее!

Пример: Example of <code>EndOfStream</code> is true - but the Position is not at the end!

+0

Почтовый поток, безусловно, смущает проблему. Сетевой поток не поддерживает поиск, и если вы читаете байты из него, то они безвозвратно теряются. Если вы не буферизируете их самостоятельно с помощью MemoryStream. Это может занять много памяти, возможно, вам придется записать ее в файл temp. –

ответ

2

Этот подход в корне несовместимы с некоторыми типами входных потоков. Потоки не требуются для поддержки Seek. Фактически, Stream имеет свойство специально определять, можно ли использовать Seek, называемый CanSeek. Код должен учитывать, что Seek может выйти из строя.

Простым, но не очень эффективным с точки зрения памяти способом является копирование содержимого вашего потока в MemoryStream. Это поддерживает Seek, и вы можете делать с ним все, что хотите. Тот факт, что вы используете ReadToEnd(), предполагает, что данные не настолько велики, что использование памяти вызовет проблему, поэтому вы, вероятно, можете просто пойти с этим.

Примечание: как указано в документе, если Seek не поддерживается, предполагается, что он должен выбросить NotSupportedException. Похоже, что с реализацией потока, с которой вы имеете дело, она не поддерживается, но не реализована должным образом. Надеюсь, по крайней мере, что CanSeek возвращает false, так что вы все еще можете надежно обнаружить это.

+0

'CanSeek' во всех случаях верен. И я не стал исключением. Вот почему я прошу вас здесь. Может быть, это ошибка с * SharpZipLib *? – Patrick

+1

@Patrick Да, это то, о чем я беспокоился и почему я включил свою заметку. Это похоже на ошибку в реализации, но обходной путь тот же: скопируйте все в «MemoryStream», и он должен работать нормально. – hvd

+0

Большое спасибо @hvd Я узнал то же самое и et voilà - это работает! – Patrick

1

Вариант 1:

XElement имеет Load() метод, который будет считывать непосредственно из потока XML. Он будет управлять кодировкой для вас внутренне. И это будет более эффективно, избегая ненужной строки. Так почему бы не использовать это.

XElement.Load(uploadStream); 

Вариант 2:

Если вы действительно хотите работать со строкой, не использовать новый XmlTextReader(). XmlTextReader.Create() имеет больше возможностей, поэтому сделайте это вместо этого:

var xmlReader = XmlTextReader.Create(uploadStream); 
var streamReaderString = xmlReader.ReadOuterXml(); 
return XElement.Parse(streamReaderString); 
+1

Хороший вызов, OP указывает: «Я хочу определить кодировку XML-документа перед его разбором». но не объясняет, почему и не использует кодировку, кроме синтаксического анализа. – hvd