"Root element not found" - when reading memory stream - c#

I have a class that i store in a list.
I serialize it ...
XmlDocument xd = new XmlDocument();
MemoryStream ms = new MemoryStream();
XmlSerializer xm = new XmlSerializer(typeof(List<BugWrapper>));
xm.Serialize(ms, _bugs);
StreamReader sr = new StreamReader(ms);
string str = sr.ReadToEnd();
xd.Load(ms);
I looked into str and found it to be empty, the collection however has an object.
Any ideas into why this happens?

Yes - you're saving to the memory stream, leaving it at the end. You need to "rewind" it with:
ms.Position = 0;
just before you create the StreamReader:
xm.Serialize(ms, _bugs);
ms.Position = 0;
StreamReader sr = new StreamReader(ms);
string str = sr.ReadToEnd();
However, you then need to rewind it again before you load into the XmlDocument unless you remove those last two lines, which I suspect were just for debugging. Just for good measure, let's close the memory stream as well when we're done with it:
using (MemoryStream stream = new MemoryStream())
{
XmlSerializer serializer = new XmlSerializer(typeof(List<BugWrapper>));
seralizer.Serialize(stream, _bugs);
stream.Position = 0;
XmlDocument doc = new XmlDocument();
doc.Load(stream);
}

Related

C# Spire Document.SaveToStream not working

I have the following code but it is just creating a 0kb empty file.
using (var stream1 = new MemoryStream())
{
MemoryStream txtStream = new MemoryStream();
Document document = new Document();
fileInformation.Stream.CopyTo(stream1);
document.LoadFromStream(stream1, FileFormat.Auto);
document.SaveToStream(txtStream, FileFormat.Txt);
StreamReader reader = new StreamReader(txtStream);
string text = reader.ReadToEnd();
System.IO.File.WriteAllText(fileName + ".txt", text);
}
I know the data is successfully loaded into document because if do document.SaveToTxt("test.txt", Encoding.UTF8);
instead of the SaveToStream line it exports the file properly.
What am I doing wrong?
When copying a stream, you need to take care to reset the position to 0 if copying. As seen in the answer here, you can do something like this to your streams:
stream1.Position = 0;
txtStream.Position = 0;

Serializing JSON with DataContractJsonSerializer in C# gives trailing null characters (\0) [duplicate]

Right now I'm using XmlTextWriter to convert a MemoryStream object into string. But I wan't to know whether there is a faster method to serialize a memorystream to string.
I follow the code given here for serialization - http://www.eggheadcafe.com/articles/system.xml.xmlserialization.asp
Edited
Stream to String
ms.Position = 0;
using (StreamReader sr = new StreamReader(ms))
{
string content = sr.ReadToEnd();
SaveInDB(ms);
}
String to Stream
string content = GetFromContentDB();
byte[] byteArray = Encoding.ASCII.GetBytes(content);
MemoryStream ms = new MemoryStream(byteArray);
byte[] outBuf = ms.GetBuffer(); //error here
using(MemoryStream stream = new MemoryStream()) {
stream.Position = 0;
var sr = new StreamReader(stream);
string myStr = sr.ReadToEnd();
}
You cant use GetBuffer when you use MemoryStream(byte[]) constructor.
MSDN quote:
This constructor does not expose the
underlying stream. GetBuffer throws
UnauthorizedAccessException.
You must use this constructor and set publiclyVisible = true in order to use GetBuffer
In VB.net i used this
Dim TempText = System.Text.Encoding.UTF8.GetString(TempMemoryStream.ToArray())
in C# may apply

How to download and open XML file via SFTP?

I need to open XML file (create XmlDocument) without creating local copy. Using SSH.NET, I came up with this code:
var connectionInfo = new ConnectionInfo("host",
"username",
new PasswordAuthenticationMethod("username", "password"));
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
System.IO.MemoryStream mem = new System.IO.MemoryStream();
client.DownloadFile("filename.xml", mem);
mem.Position=0;
using(XmlReader reader = XmlReader.Create(mem))
{
var docc = new XmlDocument();
docc.Load(mem);
}
client.Disconnect();
}
But is gets stuck on docc.Load(mem). What could be the problem?
mem object looks like this:
Note that here:
using(XmlReader reader = XmlReader.Create(mem))
{
var docc = new XmlDocument();
docc.Load(mem);
}
You are not using variable reader at all. Either change to
using(XmlReader reader = XmlReader.Create(mem))
{
var docc = new XmlDocument();
docc.Load(reader);
}
or remove reader at all:
docc.Load(mem);
While the answer by #Evk solves your immediate problem, your code is still inefficient.
Use SftpClient.OpenRead to directly stream the file to XmlReader:
using (XmlReader reader = XmlReader.Create(client.OpenRead("filename.xml"))
{
// process the XML
}
or to XmlDocument:
var docc = new XmlDocument();
docc.Load(client.OpenRead("filename.xml"));
This way, you do not waste a memory by creating another copy of the file in MemoryStream.
It looks like you wrote xml file to stream and now, stream is pointed at the end of xml file. Try setting stream.position to 0 before loading.
stream.Position = 0;
Try this:
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
System.IO.MemoryStream mem = new System.IO.MemoryStream();
client.DownloadFile("filename.xml", mem);
// Set stream position
mem.Position = 0;
using(XmlReader reader = XmlReader.Create(mem))
{
var docc = new XmlDocument();
docc.Load(mem);
}
client.Disconnect();
}
I would also change the code to dispose the memory stream correctly...

Converting Class to XML to string

I'm using XMLSerializer to serialize a class into a XML. There are plenty of examples to this and save the XML into a file. However what I want is to put the XML into a string rather than save it to a file.
I'm experimenting with the code below, but it's not working:
public static void Main(string[] args)
{
XmlSerializer ser = new XmlSerializer(typeof(TestClass));
MemoryStream m = new MemoryStream();
ser.Serialize(m, new TestClass());
string xml = new StreamReader(m).ReadToEnd();
Console.WriteLine(xml);
Console.ReadLine();
}
public class TestClass
{
public int Legs = 4;
public int NoOfKills = 100;
}
Any ideas on how to fix this ?
Thanks.
You have to position your memory stream back to the beginning prior to reading like this:
XmlSerializer ser = new XmlSerializer(typeof(TestClass));
MemoryStream m = new MemoryStream();
ser.Serialize(m, new TestClass());
// reset to 0 so we start reading from the beginning of the stream
m.Position = 0;
string xml = new StreamReader(m).ReadToEnd();
On top of that, it's always important to close resources by either calling dispose or close. Your full code should be something like this:
XmlSerializer ser = new XmlSerializer(typeof(TestClass));
string xml;
using (MemoryStream m = new MemoryStream())
{
ser.Serialize(m, new TestClass());
// reset to 0
m.Position = 0;
xml = new StreamReader(m).ReadToEnd();
}
Console.WriteLine(xml);
Console.ReadLine();
There's the [Serializabe] attribute missing on class TestClass and you have to set the position of the memory stream to the beginning:
XmlSerializer ser = new XmlSerializer(typeof(TestClass));
MemoryStream m = new MemoryStream();
ser.Serialize(m, new TestClass());
m.Position = 0;
string xml = new StreamReader(m).ReadToEnd();
Console.WriteLine(xml);
Console.ReadLine();
Your memory stream is not closed, and is positioned at the end (next available location to write in). My guess is that you must Close it, or Seek to its beginning. The way you do you don't read anything because you are already at the end of stream. So add Seek() after you serialize objects. Like this:
XmlSerializer ser = new XmlSerializer(typeof(TestClass));
MemoryStream m = new MemoryStream();
ser.Serialize(m, new TestClass());
m.Seek(0, SeekOrigin.Begin); //<-- ADD THIS!
string xml = new StreamReader(m).ReadToEnd();
Console.WriteLine(xml);
Console.ReadLine();

Namespace redefinition exception if XmlTextWriter is declared a certain way

I am bulding up an XDocument and serializing it to a UTF8 string with the following code:
string xmlString = "";
using (MemoryStream ms = new MemoryStream())
{
using (XmlWriter xw = new XmlTextWriter(ms, Encoding.UTF8))
{
doc.Save(xw);
xw.Flush();
StreamReader sr = new StreamReader(ms);
ms.Seek(0, SeekOrigin.Begin);
xmlString = sr.ReadToEnd();
}
}
This worked fine.
I then needed to toggle whether or not the declarator was serialized to the string. I changed the code to this:
string xmlString = "";
using (MemoryStream ms = new MemoryStream())
{
XmlWriterSettings settings = new XmlWriterSettings()
{
OmitXmlDeclaration = !root.IncludeDeclarator,
Encoding = Encoding.UTF8
};
using (XmlWriter xw = XmlTextWriter.Create(ms, settings))
{
doc.Save(xw);
xw.Flush();
StreamReader sr = new StreamReader(ms);
ms.Seek(0, SeekOrigin.Begin);
xmlString = sr.ReadToEnd();
}
}
This throws the following exception on doc.Save(xw):
The prefix '' cannot be redefined from
'' to 'my_schema_here' within the same
start element tag.
I am trying to figure out why the XDoc can be saved if the writer is "new"ed up, but not if it is ".Create"d. Any ideas?
Jordon
I fixed this by adding the namespace to the name of the root element in the XDocument. Still, it's strange that this isn't necessary if "new XmlTextWriter()" is used instead of "XmlTextWriter.Create()" or "XmlWriter.Create()".
Jordon

Categories

Resources