Binary Serialization of an Observable Collection -- Saving, Loading - c#

I am having a problems creating binary serialization for my observable collection of Contacts Objects. The Person Object contains the firstname,lastname, and age properties.
The collection is called NewAccountList.
I want to be able to persist my collection data by saving it to a file. This action currently occurs when the save button is clicked, but it does xml serialization instead of binary serialization.
private void MenuItem_Click_2(object sender, RoutedEventArgs e)
{
// Create OpenFileDialog
Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();
XmlSerializer xs = new XmlSerializer(typeof(ObservableCollection));
sfd.Filter = "XML files (.xml)|.xml";
// Display OpenFileDialog by calling ShowDialog method
Nullable<bool> result = sfd.ShowDialog();
try
{
using (StreamWriter wr = new StreamWriter("SavedAccounts.xml"))
{
xs.Serialize(wr, NewAccountList);
}
}
catch
{}
}
Would anybody be able to give me a good example of how to save a collection of objects?

full code example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
using (FileStream fs = File.Create("data.hffgfh"))
{
bf.Serialize(fs, 123456);
}
}
}
}
output:

Try changing .xml to .bin. That should fix your problem

Related

WinForms how to open file in resources folder

I am new in WinForms technology. I am using .NET Framework 4.8 , Microsoft Visual Studio 2019. I put file in Resources folder.
I tried something like this
using DevExpress.XtraBars;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace accwf
{
public partial class NhapSoDu : DevExpress.XtraBars.Ribbon.RibbonForm
{
public NhapSoDu()
{
InitializeComponent();
}
private void simpleButton1_Click(object sender, EventArgs e)
{
Console.WriteLine(System.AppDomain.CurrentDomain.BaseDirectory);
Process.Start(".../B01-DN_01_Summary.xlsx");
}
}
}
please guide me finish it.
I do this in one of my applications to open a XLSX file that is an embedded resource in my application
private void buttonOpenTemplate_Click(object sender, EventArgs e)
{
byte[] templateFile = Properties.Resources._01__So_du_tai_khoan; // This is your Excel document in the application Resources
string tempPath = $"{Path.GetTempFileName()}.xlsx";
using (MemoryStream ms = new MemoryStream(templateFile))
{
using(FileStream fs = new FileStream(tempPath, FileMode.OpenOrCreate))
{
ms.WriteTo(fs);
fs.Close();
}
ms.Close();
}
Process.Start(tempPath);
}
This requires a reference to System.IO for access to the MemoryStream and FileStream classes.
You are currently only outputting the base directory. Along with that, you're only looking for files within that base directory. Execution happens from the base directory, so your program is looking for ..\Path\to\exe\B01-DN_01_Summary.xlsx when it should be looking for ..\Path\to\exe\Resources\FilesHere\ImportExcel\B01-DN_01_Summary.xlsx
To note: embedding resources files into your application is not recommend. It's preferable to instead store their locations and allow the application to traverse your directories to find the specified file locations.
Here's an adapted version you can try:
You will need to make sure that the Copy to Output Directory property for you desire file is set to "Copy Always" or "Copy if Newer". This will ensure the directory path is created in your output directory.
namespace accwf
{
public partial class NhapSoDu : DevExpress.XtraBars.Ribbon.RibbonForm
{
public NhapSoDu()
{
InitializeComponent();
}
private void simpleButton1_Click(object sender, EventArgs e)
{
string resourcePath = System.IO.File.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Resources\\FilesHere\\ImportExcel\\B01-DN_01_Summary.xlsx")
if (File.Exists(resourcePath))
{
MessageBox.Show("Exists");
}
else
{
MessageBox.Show("Doesn't Exist");
}
Process.Start(resourcePath);
}
}
}
This is an example of how I get PDF file documentation for a help menu I have:
public void MyMethod()
{
// helpMenuPath is a global var set to something like: Area/MyApp/Resources/
string filePath = helpMenuPath;
string[] fileNames = new string[0]; // Initialize the variable with length of 0. Directory.GetFiles() will allow for this length to be overwritten
// Try/Catch in case bad dir
try
{
fileNames = Directory.GetFiles(filePath);
}
catch (IOException ioe)
{
// error catch for if bad dir
MessageBox.Show($"Error in getting files: {ioe.Message}");
}
// Do something with files ...
}

Get the path of the file that launched my app

I'm working in my own PDF Reader using C# & Patagames/PDFium library and I am able to open files using "OpenFileDialog" and show them on the screen. However, due requirements of the boss I am not allowed to have any buttons in the screen. All we want is to click the any .PDF file (For example, in this route: C:\Users\Adaptabilidad\Desktop\Test.pdf) and launch it & show the PDF document directly, without looking for the directory of the file. I've set my ".exe" as default app, although, the PDF Reader is executed no PDF file is displayed.
I've tried Application.ExecutablePath, Application.StartUpPath after initializing the component and I'm still getting the route of my PDF reader executable (.Exe) but I need to know what the file to be open is (filepath).
How can I get the information about the .pdf file (directory can vary) that is launching my app? You can see my code below if helps.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Patagames;
using System.IO;
namespace aPDF
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void toolStripButton1_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "PDF Files (*.pdf)|*.pdf";
if (dialog.ShowDialog() == DialogResult.OK)
{
openfile(dialog.FileName);
}
}
public void openfile(string filepath)
{
byte[] bytes = System.IO.File.ReadAllBytes(filepath);
var stream = new MemoryStream(bytes);
Patagames.Pdf.Net.PdfDocument pdfDocument = Patagames.Pdf.Net.PdfDocument.Load(stream);
pdfViewer1.Document = pdfDocument;
}
}
}
Updates:
I've found a way. One of you guys that commented allowed me to find out how to do it.
What I used is the following sentence in my Program.cs:
public static string[] cmdLine = Environment.GetCommandLineArgs();
public static string cmd = cmdLine[1];
Then, y use "cmd" as filepath.
Why? Environment.GetCommandLineArgs(); returns 2 values, the .exe you're executing (your program) & as second value the file that you've used in order to launch that .exe.
That's it. Thank you for your answers.

How to set or clear the Author in OpenXML SpeadsheetDocument

When creating a spreadsheet with the OpenXML SpreadsheetDocument class in C#.Net, the Authors and Last saved by fields are set to "James Westgate".
How do I clear or overwrite James' name?
SpreadsheetDocument doc = SpreadsheetDocument.Open(stream, true);
doc.PackageProperties.Creator = "sh";
...is not working for me.
Update:-
using System;
using System.Windows.Forms;
using System.IO;
using DocumentFormat.OpenXml.Extensions;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
namespace OpenXMLProps
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public MemoryStream Execute()
{
MemoryStream stream = SpreadsheetReader.Create();
using (SpreadsheetDocument doc = SpreadsheetDocument.Open(stream, true))
{
WorksheetPart worksheetPart = SpreadsheetReader.GetWorksheetPartByName(doc, "Sheet1");
WorksheetWriter writer = new WorksheetWriter(doc, worksheetPart);
doc.PackageProperties.Creator = "Finbar mahoolahan";
SpreadsheetWriter.Save(doc);
return new MemoryStream(stream.ToArray());
}
}
private void button1_Click(object sender, EventArgs e)
{
using (FileStream fs = new FileStream("excel_test.xlsx", FileMode.Create, FileAccess.Write))
{
MemoryStream excel_stream = Execute();
excel_stream.WriteTo(fs);
}
}
}
}
This works for me (after NuGet-ing in the OpenXml package):
using (var doc = SpreadsheetDocument.Open(#"C:\tmp\MyExcelFile.xlsx", true))
{
var props = doc.PackageProperties;
props.Creator = "Flydog57";
props.LastModifiedBy = "Flydog57";
doc.Save();
}
It even worked the first time I tried it! That's an unusual occurrence.
I believe (without looking at the code which is probably 8yrs old by now) that there is a base document which forms the template and this probably has my name associated with it. This is embedded as a resource in the dll.
I suggest trying to download the original SimpleOOXml source code from CodePlex and try modifying the document. You could recompile against a modern version of the OpenXML library too.

Deserializing a file into List C#

I'm trying to deserialize a file which contains objects into a list of objects
but for some how the list takes to objects only
here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace Test
{
class Program
{
static void Main(string[] args)
{
user lastuser = new user("First name", "Last name", "Username", "Password");
FileStream ToStream = new FileStream("UsersDB.txt", FileMode.OpenOrCreate);
BinaryFormatter Ser = new BinaryFormatter();
List<user> ToUsers = new List<user>();
try
{
ToUsers = (List<user>)Ser.Deserialize(ToStream); // this is to deserialize everything in the file to the list
ToUsers.Add(lastuser); // here we are adding our object (which is lastuser) to the list
Ser.Serialize(ToStream, ToUsers); // here we are serializing the list back to the file
}
catch (System.Runtime.Serialization.SerializationException)
{//this is to catch the exception if the file was empty and there is nth to deserialize to the list
ToUsers.Add(lastuser);
Ser.Serialize(ToStream, ToUsers);
}
ToStream.Close();
Console.WriteLine("ToUsers objects : " + ToUsers.Count());
// this is to see how many objects does the list have
}
}
}
and this is the class I'm serializing:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
namespace Test
{
[Serializable]
class user
{
private string Fname, Lname, Username, Password;
public user()
{ }
public user(string Fname, string Lname, string Username, string Password)
{
this.Fname = Fname;
this.Lname = Lname;
this.Username = Username;
this.Password = Password;
}
public string GetUsername()
{
return Username;
}
}
}
When I run it, I get the count of list is 1.
Run it again I get it 2.
Run it 1000 times and you will get 2.
I know there is something wrong so please help me.
Your code within try is
try
{
ToUsers = (List<user>)Ser.Deserialize(ToStream);
ToUsers.Add(lastuser);
Ser.Serialize(ToStream, ToUsers);
}
what is happening in the above code is, during de-serialization, the stream position pointer is moved to the end of the file. So when you serialize back, the list containing the two objects is appended at the end of the file.
Hence, the new file structure is like
+---------------------+-----------------------------------------------------+
| List (1 user info) | List (2 user's info) |
+---------------------+-----------------------------------------------------+
So, when you de-serialize the next time, you again get the list containing one user's details.
To overwrite the existing data, reset the stream position pointer to the beginning of the file using
ToStream.Seek(0, SeekOrigin.Begin);
Hence, your try block would look like
try
{
ToUsers = (List<user>)Ser.Deserialize(ToStream);
ToStream.Seek(0, SeekOrigin.Begin);
ToUsers.Add(lastuser);
Ser.Serialize(ToStream, ToUsers);
}
The problem is that you're deserializing the first list with one object, adding the item and appending the new list to the file. Next time you open/read the file, you'll read the first list again.
What you need to do is simply rewind the FileStream before serializing the new list to the file;
ToUsers = (List<user>)Ser.Deserialize(ToStream);
ToUsers.Add(lastuser); // here we are adding our object (which is lastuser) to the list
ToStream.Seek(0, SeekOrigin.Begin);
Ser.Serialize(ToStream, ToUsers); // here we are serializing the list back to the file

Edit .Bat File In C#

Well, first of all my code :
protected void Button2_Click1(object sender, EventArgs e)
{
string batname = edit.SelectedValue;
StreamWriter sw = new StreamWriter("D:\\MPSite-Serv\\bats\\" + batname);
string theedit = batedit.Text;
sw.WriteLine(theedit);
sw.Flush();
}
When I click on button2 and try to write all of the text into the bat file, I get this result the bat file contains:
System.Web.UI.WebControls.TextBox
Why is that?
I am using all of the following statements, if it helps:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Diagnostics;
You are getting the type name of the textbox, which leads me to believe that your code rather looks something like:
sw.WriteLine(batedit);
I.e. you are sending the textbox object itself to be written to the file instead of the contents of its Text property. This will implicitly call the ToString method, which by default returns the type name of the object.
Also, you are not closing the StreamWriter properly, which might cause problems when you want to use it. You should call the Close method, and you don't have to call Flush before closing the StreamWriter. Alternatively you can put the StreamWriter in a using block, which would dispose it automatically, which will close it.
http://msdn.microsoft.com/en-us/library/system.io.streamwriter.aspx#Y2863
The problem is simple: sw.writeline expects a string. You are sending it a text object which gets turned into the aformentioned .ToString(); which means your line gets translated, loosely, into
sw.WriteLine(theedit.ToString());
if you look at the documentation for WebControls.TextBox... scroll down the list to the Method ToString()
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.textbox.aspx
What you need to do... is give it one string at a time (although I assume you could just give it the raw string from the textbox):
using System.IO;
namespace String_Writer
{
class Program
{
static void Main(string[] args)
{
string batname = "test.txt";
string theedit = "Testing one two three four\n\nfive six seven eight.";
using(StreamWriter sw = File.CreateText("C:\\Users\\Kriis\\Desktop\\" + batname))
{
using (StringReader reader = new StringReader(theedit))
{
string line = string.Empty;
do
{
line = reader.ReadLine();
if (line != null)
{
sw.WriteLine(line);
}
} while (line != null);
}
}
}
}
}

Categories

Resources