Save object to file - What are common alternate serialization methods? - c#

Edit: The original question was made out of a misunderstanding, and has been updated.
Coming from other languages it seems odd that C# does not seem to have a simple way to dump things like objects and components straight to file.
Lets take java as an example, where I can dump any object to file and load with no apparent restrictions:
//Save object to file:
FileOutputStream saveFile = new FileOutputStream(---filePath---);
ObjectOutputStream save = new ObjectOutputStream(saveFile);
save.writeObject(---YorObjectHere---);
//Load object from file
FileInputStream saveFile = new FileInputStream(---filePath---);
ObjectInputStream save = new ObjectInputStream(saveFile);
---ObjectType--- loadedObject = (---ObjectType---) save.readObject();
Can this sort of thing be easily achieved in C#?
I have tried the standard method of serialization:
//Save object to file:
IFormatter formatterSave = new BinaryFormatter();
Stream streamSave = new FileStream(---filePath---, FileMode.Create, FileAccess.Write, FileShare.None);
formatterSave.Serialize(streamSave, ---ObjectToSave---);
//Load object from file
IFormatter formatterLoad = new BinaryFormatter();
Stream streamLoad = new FileStream(---filePath---, FileMode.Open, FileAccess.Read, FileShare.Read);
---ObjectType--- ---LoadedObjectName--- = (---ObjectType---)formatterLoad.Deserialize(streamLoad);
While this method is quite simple to do, it does not always work with existing or locked code because the [serializable] tag cannot always be added.
So what is the best alternate for serialization?
Thanks to comments I tried the XML method, but it did not work either because it cannot serialize an ArrayList as shown on MSDN
//Save object to file:
var serializerSave = new XmlSerializer(typeof(objectType));
writer = new StreamWriter(filePath, append);
serializerSave.Serialize(writer, objectToWrite);
//Load object from file
var serializerLoad = new XmlSerializer(typeof(objectType));
reader = new StreamReader(filePath);
return (T)serializerLoad.Deserialize(reader);
It looks like JSON is the only way to do it easily, or is there another alternate way to serialize with normal C# libraries without needing massive amounts of code?

Thanks to those who commented and pointed me in the right direction.
Although its not covered in the basic libraries, using JSON looks like the best alternate in this situation, I plan to use Json.NET, it can be found here: http://www.nuget.org/packages/Newtonsoft.Json
Another good option is Google Gson: https://code.google.com/p/google-gson/

Related

How do I save a file stream straight to an excel file in C#? [duplicate]

This question already has an answer here:
OPEN XML to Export 2007/2010
(1 answer)
Closed 3 years ago.
To give you a bit of context I'm trying to download a bunch of attachments in one bulk operation. These attachments are normally downloaded via a website a file at a time and the MVC controller code which retrieves the attachment looks something like this:
var attachment = _attachmentsRepository.GetAttachment(websiteId, id);
if (attachment.FileStream == null || !attachment.FileStream.CanRead)
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
var content = new StreamContent(attachment.FileStream);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = $"{id}.{attachment.Extension}" };
return new HttpResponseMessage(HttpStatusCode.OK) { Content = content };
What I'm trying to do is write a console application for the bulk operation which will save each file directly to disk and sofar what I've got for a single file save is:
var = attachment attachmentsRepository.GetAttachment(websiteId, resource.Id);
attachment.FileStream.Position = 0;
var reader = new StreamReader(attachment.FileStream);
var content = reader.ReadToEnd();
File.WriteAllText(someFilePath, content);
I've side-stepped any http specific framework classes since I just need to download directly to file via code instead of the browser. This code successfully generates files but when I open them Excel indicates that they're corrupted which I suspect is an encoding issue. I'm currently playing around with the encoding at the moment but sofar not much luck so any help is appreciated.
Don't use StreamReader for processing binary data. The StreamReader/StreamWriter classes are for reading and writing human-readable text in a Stream and as such they attempt to perform text encoding/decoding which can mangle binary data (I feel the classes should be renamed to StreamTextReader/StreamTextWriter to reflect their inheritance hierarchy).
To read raw binary data, use methods on the Stream class directly (e.g. Read, Write, and CopyTo).
Try this:
var attachment = ...
using( FileStream fs = new FileStream( someFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize: 8 * 1024, useAsync: true ) )
{
await attachment.FileStream.CopyToAsync( fs );
}
The using() block will ensure fs is flushed and closed correctly.

Writing Data into a File on Hololens

in my Hololens app i want to write data into a file which i can then view over the Device Portal. The Data contains just the time from one airtap on a special object to another airtap.
The problem ist that there will be no file created in the Device Portal under /LocalAppData/YourApp/LocalState
Thanks in advance
Jonathan
public void StopTime()
{
TimeSpan ts = time.Elapsed;
time.Stop();
path = Path.Combine(Application.persistentDataPath, "Messdaten.txt");
using (TextWriter writer = File.CreateText(path))
{
writer.Write(ts);
}
}
I usually use a FileStream and a StreamWriter and make sure the FileMode.Create is set.
See also How to write text to a file for more approaches
using (var file = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write))
{
using (var writer = new StreamWriter(file, Encoding.UTF8))
{
writer.Write(content);
}
}
With that I never had any trouble on the HoloLens so far.
You also might want to use something like ts.ToString() in order to format the value to your needs.
Alternatively you could also try Unity's Windows.File (only available for UWP) but than you need to have byte[] as input. E.g. from here
long c = ts.Ticks;
byte[] d = BitConverter.GetBytes(c);
File.WriteAllBytes(path, d);
The simplest thing to do is to use File.WriteAllText method https://learn.microsoft.com/en-us/dotnet/api/system.io.file.writealltext?view=netframework-4.7.2
Obviously there are many ways that could work but it is good to stick to the simplest solution.

Binary serialization, IFormatter: use a new one each time or store one in a field?

Using binary formatting for 1st time in .net C#
Code from MSDN is like this:
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.lvl", FileMode.Create, FileAccess.Write,FileShare.None);
formatter.Serialize(stream, Globals.CurrentLevel);
stream.Close();
Just wondering should I store an IFormatter in a field in my class and use it over and over again or should I do as above and instantiate a new one every time I save/load something?
I noticed it is not IDisposable.
There's very little overhead in re-creating a BinaryFormatter, most of the properties it sets in the constructor are enums, see here (thanks to Reflector):
public BinaryFormatter()
{
this.m_typeFormat = FormatterTypeStyle.TypesAlways;
this.m_securityLevel = TypeFilterLevel.Full;
this.m_surrogates = null;
this.m_context = new StreamingContext(StreamingContextStates.All);
}
If you were going to re-use it though, you'd need to synchronize access to the Serialize and Deserialize methods to keep them thread-safe.

asp.net filehelpers write file to client directly

I'm using the FileHelpers library for a C# .net project. All is working ok except I need to have the generated CSV savable via a button click.
So the user clicks a button and they get a prompt to save the file. I know Filehelpers has a WriteStream option but their own documentation shows only an example of WriteFile. I don't know if WriteStream is what's needed but I think it is.
Anyone know if it's possible to have the CSV file saved directly to the client rather than to the server hard drive?
Thanks.
UPDATE WITH MORE DETAIL:
I'll try to give more detail to help clarify what it is I'm trying to achieve. I don't want to save any file on the server. I am using FileHelpers to generate a record and I want to try and use their WriteStream method to write that record as a CSV directly to their browser; but the example they provide doesn't actually use that method at all, strangely.
Here's the link to their method:
http://www.filehelpers.com/FileHelpers.FileHelperEngine.WriteStream_overload_2.html
And here's the method in question.
public void WriteStream(
TextWriter writer,
IEnumerable records,
int maxRecords
);
I can easily save the file to the server but don't want to as I've no need for it and want to get the client to save it directly to their own machine.
It may be that I have to go through the normal route to achieve this but I saw the WriteStream method and thought maybe FileHelpers facilitated a nice clean way of achieving the same result.
Hope this is clearer.
You should be able to do something like the following:
Response.ContentType = #"application/x-msdownload";
Response.AppendHeader("content-disposition", "attachment; filename=" + FILE_NAME);
Response.Write(csv.ToString());
Response.Flush();
Response.End();
There are plenty of more elaborate suggestions on StackOverflow such as this one. It depends what you are trying to achieve.
EDIT
I think the steps you are missing are:
MemoryStream stream = new MemoryStream();
StreamWriter streamWriter = new StreamWriter(stream);
engine.WriteStream(streamWriter, records);
stream.Position = 0;
and then you can use
StreamReader reader = new StreamReader(stream);
Response.Write(reader.ReadToEnd);
instead of Response.Write(csv.ToString()) in my first example above.
Don't forget to flush StreamWriter. See example
public MemoryStream CreateCsvFileAsMemoryStream(List<TestItem> testItems) {
var engine = new FileHelperEngine<TestItemCsvMapping>();
var items = testItems.Select(ti => (TestItemCsvMapping)ti).ToList();
engine.HeaderText = engine.GetFileHeader();
var ms = new MemoryStream();
var sw = new StreamWriter(ms);
engine.WriteStream(sw, items);
sw.Flush();
//var reader = new StreamReader(ms);
//ms.Position = 0;
//Console.Write(reader.ReadToEnd());
ms.Position = 0;
return ms;
}

Object Serialization -Binaryformatter , how to write at the and / insert data with in already existing file?

i want to write my file which contains list of file names , i am storing this local disk,
whenever i write the file , all existing data are erasing and new data is over writing , i am failing to keep the existing data and start writing after the line of existing data
my Binary format writer codes goes like this
private object ReadFileToUI(string filename)
{
Stream readStr = File.OpenRead(filename);
BinaryFormatter rbf = new BinaryFormatter();
object obj= rbf.Deserialize(readStr);
readStr.Close();
return obj;
}
and my binary writer goes like thsi ,
Stream str = File.OpenWrite(fileName);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(str, fl);
str.Close();
suppose if i have already 10 objects inside the file , any new writing should be treated as the 11th and onward so on and previous data should not be affected in the file ??
Open your stream like this...
Stream str = File.Open(fileName, FileMode.Append, FileAccess.Write);

Categories

Resources