I got this block of code from the NHibernate 3 Cookbook (an excellent book, btw), and while I couldn't find anyting in the errata about it. I'm getting the error "Cannot access a closed stream":
var settings = new XmlWriterSettings { Indent = true };
var serializer = new XmlSerializer(typeof(HbmMapping)); // todo: probably should abstract this out, at least optionally
using (var memStream = new MemoryStream(2048))
using (var xmlWriter = XmlWriter.Create(memStream, settings))
{
serializer.Serialize(xmlWriter, hbmMapping);
memStream.Flush();
memStream.Position = 0;
using (var sr = new StreamReader(memStream))
{
return sr.ReadToEnd();
}
}
The error is thrown on the sr.ReadToEnd() line.
Found a similar problem after all, Why disposing StreamReader makes a stream unreadable? . Basically, I removed the using that was around the reader and all is well.
Related
Good evening,
I realize an application currently using the C # language and I had to resort to serialization using XmlSerializer.
I had to be able to save a list in an xml file. It was then necessary that I could recover the data of this file to be able to recover the list. I managed to do all this and here is my code:
To save the list:
Stream stream = File.OpenWrite(chemin);
XmlSerializer xmlSer = new XmlSerializer(typeof(List<Utilisateur>));
xmlSer.Serialize(stream,listeUtilisateurs);
stream.Close();
To retrieve the list:
Stream stream = File.OpenRead(chemin);
XmlSerializer xmlSer = new XmlSerializer(typeof(List<Utilisateur>));
List<Utilisateur> listrecuperee = (List<Utilisateur>)xmlSer.Deserialize(stream);
listeUtilisateurs = listrecuperee;
stream.Close();
However, the problem is that every time I save the list, the data that was before it go away, I want to keep it, I actually want it to write after the file. Would you have a solution please? Cordially.
Yes, we can do what you want.
Code to serialize to the same file:
var xmlSer = new XmlSerializer(typeof(List<Utilisateur>));
var xmlWriterSettings = new XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent = true // need only for pretty print
};
bool append = File.Exists("test.txt");
using (var streamWriter = new StreamWriter("test.txt", append))
using (var xmlWriter = XmlWriter.Create(streamWriter, xmlWriterSettings))
{
xmlSer.Serialize(xmlWriter, listeUtilisateurs);
streamWriter.WriteLine(); // need only for pretty print
}
Code for reading a set of data:
int orderNumber = 2; // for example, read the second data collection in order
var xmlReaderSettings = new XmlReaderSettings
{
ConformanceLevel = ConformanceLevel.Fragment
};
using (var reader = XmlReader.Create("test.txt", xmlReaderSettings))
{
int count = 0;
while (reader.ReadToFollowing("ArrayOfUtilisateur"))
{
count++;
if (count == orderNumber)
break;
}
var list = (List<Utilisateur>)xmlSer.Deserialize(reader);
}
Of course, you need to add the necessary checks when reading.
This way of using a single file is pretty ugly, though it works. Therefore, consider other options for saving your data.
I am trying to create a csv with Headers that are going to be use in Multiple languages. this is the current Code that i am using and works for English but not for Japanese as example.
What is the best way to do that? should i have to specify the Culture Info? i tried that but not good results.
Thanks.
private byte[] WriteCsvToMemory(IEnumerable records)
{
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream, Encoding.UTF8))
using (var csvWriter = new CsvWriter(streamWriter))
{
csvWriter.WriteField(GetResourceFileValue("ja-jp", "KEY"));
csvWriter.NextRecord();
csvWriter.Configuration.HasHeaderRecord = false;
csvWriter.WriteRecords(records);
streamWriter.Flush();
return memoryStream.ToArray();
}
}
i made a mistake on my code the solution is simple:
using (var streamWriter = new StreamWriter(memoryStream, **Encoding.UTF8** ))
Nothing wrong with the the library.
Having some problems with CsvHelper and writing to a memory stream. I've tried flushing the stream writer and setting positions and everything else tried. I figure I've narrowed it down to a really simple test case that obviously fails. What am I doing wrong here?
public OutputFile GetTestFile()
{
using (var ms = new MemoryStream())
using (var sr = new StreamWriter(ms))
using (var csv = new CsvWriter(sr))
{
csv.WriteField("test");
sr.Flush();
return new OutputFile
{
Data = ms.ToArray(),
Length = ms.Length,
DataType = "text/csv",
FileName = "test.csv"
};
}
}
[TestMethod]
public void TestWritingToMemoryStream()
{
var file = GetTestFile();
Assert.IsFalse(file.Data.Length == 0);
}
Editing the correct answer in for people googling as this corrected code actually passes my test. I have no idea why writing to a StringWriter then converting it to bytes solves all the crazy flushing issues, but it works now.
using (var sw = new StringWriter())
using (var csvWriter = new CsvWriter(sw, config))
{
csvWriter.WriteRecords(records);
return Encoding.UTF8.GetBytes(sw.ToString());
}
Since CSVHelper is meant to collect several fields per row/line, it does some buffering itself until you tell it the current record is done:
csv.WriteField("test");
csv.NextRecord();
sr.Flush();
Now, the memstream should have the data in it. However, unless there is more processing elsewhere, the result in your OutputFile is wrong: Data will be byte[] not "text/csv". It seems like StringWriter would produce something more appropriate:
string sBuff;
using (StringWriter sw = new StringWriter())
using (CsvWriter csv = new CsvWriter(sw))
{
csv.WriteRecord<SomeItem>(r);
sBuff = sw.ToString();
}
Console.WriteLine(sBuff);
"New Item ",Falcon,7
I want to use the DataContractJsonSerializer to serialize to file in JsonFormat.
The problem is that the WriteObjectmethod only has 3 options XmlWriter, XmlDictionaryWriter and Stream.
To get what I want I used the following code:
var js = new DataContractJsonSerializer(typeof(T), _knownTypes);
using (var ms = new MemoryStream())
{
js.WriteObject(ms, item);
ms.Position = 0;
using (var sr = new StreamReader(ms))
{
using (var writer = new StreamWriter(path, false))
{
string jsonData = sr.ReadToEnd();
writer.Write(jsonData);
}
}
}
Is this the only way or have I missed something?
Assuming you're just trying to write the text to a file, it's not clear why you're writing it to a MemoryStream first. You can just use:
var js = new DataContractJsonSerializer(typeof(T), _knownTypes);
using (var stream = File.Create(path))
{
js.WriteObject(stream, item);
}
That's rather simpler, and should do what you want...
I am actually quite terrified to claim to know something that Jon Skeet doesn't, but I have used code similar to the following which produces the Json text file and maintains proper indentation:
var js = new DataContractJsonSerializer(typeof(T), _knownTypes);
using (var stream = File.Create(path))
{
using (var writer = JsonReaderWriterFactory.CreateJsonWriter(stream, Encoding.UTF8, true, true, "\t"))
{
js.WriteObject(writer, item);
writer.Flush();
}
}
(as suggested here.)
After writing and reading an xml string to and from a stream, it ceases to be deserializable. The new string is clipped.
string XmlContent = getContentFromMyDataBase();
XmlSerializer xs = new XmlSerializer(typeof(MyObj));
MemoryStream ms = new MemoryStream();
StreamWriter sw = new StreamWriter(ms);
char[] ca = XmlContent.ToCharArray(); // still working up to this point.
ms.Position = 0;
sw.Write(ca);
StreamReader sr = new StreamReader(ms);
ms.Position = 0;
string XmlContentAgain = sr.ReadToEnd();
Console.WriteLine(XmlContentAgain); // (outputstring is too short.)
MyObj theObj = (MyObj)xs.Deserialize(ms); // Can't deserialize.
Any suggestions as to how to fix this or what is causing the problem? My only guess is that there is some form of encoding issue, but I wouldn't know how to go about finding/fixing it.
Additionally, myObj has a generic dictionary member, which typically isn't serializable, so I have stolen code from Paul Welter in order to serialize it.
Try flushing and disposing or even better simplify your code using a StringReader:
string xmlContent = getContentFromMyDataBase();
var xs = new XmlSerializer(typeof(MyObj));
using (var reader = new StringReader(xmlContent))
{
var theObj = (MyObj)xs.Deserialize(reader);
}
Note: The getContentFromMyDataBase method also suggests that you are storing XML in your database that you are deserializing back to an object. Don't.
You need to Flush or Close (closing implicitly flushes) the StreamWriter, or you cannot be sure it is done writing to the underlying stream. This is because it is doing some internal buffering.
Try this:
using(StreamWriter sw = new StreamWriter(ms))
{
char[] ca = XmlContent.ToCharArray(); // still working up to this point.
ms.Position = 0;
sw.Write(ca);
}
StreamReader sr = new StreamReader(ms);
ms.Position = 0;
string XmlContentAgain = sr.ReadToEnd();