2016-06-18 14 views
4

Ich möchte die Codierung eines XML-Dokuments vor der Analyse erkennen. So fand ich auf dem Stapel Überlauf dieses Skript.C# EndOfStream immer wahr - Suche/Position auf 0 funktioniert nicht

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); 
} 

Aber es funktioniert nicht. Immer bekomme ich EndOfStreamwahr. Aber es ist nicht !!!! -.-

Zum Beispiel habe ich die Zeichenfolge <test></test>. Beginn: 0, Ende: 13

Wenn ich ReadToEnd oder MoveToContent dann ist das Ende erfolgreich erreicht. Die EndOfStream ist wahr dann.

Wenn ich die Position über Seek oder Position-0 (zum Beispiel) dann setzen Sie ein new StreamReader zeigt immer EndOfStream ist wahr.

Die Sache ist, dass die uploadStream ist ein Stream, den ich nicht schließen kann.

Es ist ein SharpZipLib Stream eines HTTP-Upload-Stream. Also kann ich diesen Stream nicht schließen. Ich kann nur damit arbeiten.

Und das Schlimme ist nur, weil Position und Seek nicht ... Nur weil ReadToEnd Relais auf diesen Position. - Sonst würde es funktionieren. Ich denke!

Vielleicht können Sie sich mit dieser Situation :-)

Vielen Dank im Voraus helfen!

Beispiel: Example of <code>EndOfStream</code> is true - but the Position is not at the end!

+0

Der Zip-Stream verschleiert das Problem sicherlich. Ein Netzwerk-Stream unterstützt das Suchen nicht und wenn Sie Bytes von ihm lesen, sind sie unwiederbringlich verloren. Es sei denn, Sie puffern sie selbst mit einem MemoryStream. Das kann viel Speicher belegen, Sie müssen es möglicherweise in eine temporäre Datei schreiben. –

Antwort

2

Dieser Ansatz ist grundsätzlich unvereinbar mit einigen Eingangsströmen. Streams müssen Seek überhaupt nicht unterstützen. Tatsächlich hat Stream eine Eigenschaft speziell zu erkennen, ob Seek verwendbar ist, CanSeek genannt. Der Code muss berücksichtigen, dass Seek fehlschlagen kann.

Der einfache, aber nicht sehr speichereffiziente Weg besteht darin, den Inhalt des Streams in eine MemoryStream zu kopieren. Dieser unterstützt Seek, und Sie können dann tun, was Sie wollen. Die Tatsache, dass Sie ReadToEnd() verwenden, deutet darauf hin, dass die Daten nicht so groß sind, dass die Speicherbelegung ein Problem verursacht, also können Sie wahrscheinlich einfach damit fortfahren.

Hinweis: wie dokumentiert, wenn Seek nicht unterstützt wird, soll es eine NotSupportedException werfen. Es sieht aus wie bei der Stream-Implementierung, mit der Sie es zu tun haben, es wird nicht unterstützt, aber nicht richtig implementiert. Ich hoffe zumindest, dass CanSeekfalse für Sie zurückgibt, damit Sie dies immer noch zuverlässig erkennen können.

+0

'CanSeek' ist in allen Fällen wahr. Und ich habe keine Ausnahme. Deshalb bitte ich dich hier. Vielleicht ist es ein Fehler mit * SharpZipLib *? – Patrick

+1

@Patrick Ja, darum habe ich mir Sorgen gemacht und warum ich meine Notiz beigefügt habe. Das sieht wie ein Fehler in der Implementierung aus, aber die Problemumgehung ist die gleiche: Kopieren Sie alles in einen 'MemoryStream' und es sollte gut funktionieren. – hvd

+0

Vielen Dank @hvd Ich fand das gleiche und et voilà - es funktioniert! – Patrick

1

Option 1:

XElement hat eine Load() Methode, die direkt aus einem XML-Datenstrom gelesen wird. Es wird intern die Kodierung für Sie verwalten. Und es wird effizienter, wenn man eine unnötige Saite vermeidet. Warum also nicht benutzen?

XElement.Load(uploadStream); 

Option 2:

Wenn Sie wirklich mit einem String arbeiten möchten, nicht new XmlTextReader() verwenden. Die XmlTextReader.Create() hat mehr Funktionen, also tun Sie dies stattdessen:

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

Guten Ruf, das OP sagt "Ich möchte die Codierung eines XML-Dokuments vor der Analyse zu erkennen." erklärt aber nicht warum und verwendet die Codierung außer zum Parsen nicht. – hvd