Catch XML with custom Classes - c#

I have so many clases, but I want to catch the sent and the recived information via XML ... The thing is that I don't want to create a Serializer every time i catch an XML doc, so I want to ask you if anyone know how to pack a class type into a TypeOf()
Im trying to create a function that Works something like this:
public void createXML(string fileName, string route)
{
System.Xml.Serialization.XmlSerializer serializador = new System.Xml.Serialization.XmlSerializer(typeof(THIS IS WHAT I WANNA CHANGE TO A VARIABLE PARAMETER));
System.IO.FileStream stream = new System.IO.FileStream(#""+ route + fileName + ".xml", System.IO.FileMode.Create);
}
So what I want to do is to call this function and créate an XML whenever I want, but the thing is that inside the TypeOf() command, I can't figure out a way to put different classes there.

Use generics for this task.
public void createXML<T>(string fileName, string route)
{
System.Xml.Serialization.XmlSerializer serializador = new System.Xml.Serialization.XmlSerializer(typeof(T));
System.IO.FileStream stream = new System.IO.FileStream(#""+ route + fileName + ".xml", System.IO.FileMode.Create);
}

Ok, so i got this so far and if i put the route manually it Works, if i put a custom route is brings an error message saying something about the provided route formant isnt admited, this is my code ... I get the directory, créate it if its not there, then i créate the name of the file, but when i try to créate the XML it just pops the error:
public string[] createDir(string flow, int enclosure, string transaction, string method)
{
DateTime Hoy = DateTime.Now;
libs.Catalogos objCatalogos = new libs.Catalogos();
string day, month, year, hora, min, seg, time, ruta, fileName, name;
string[] datos = new string[2];
int existe;
name = objCatalogos.convertRecinto(enclosure);
day = System.DateTime.Now.ToString("dd");
//day = "13";
month = System.DateTime.Now.ToString("MM");
year = System.DateTime.Now.ToString("yyyy");
hora = System.DateTime.Now.ToString("HH");
min = System.DateTime.Now.ToString("mm");
seg = System.DateTime.Now.ToString("ss");
time = hora + "_" + min + "_" + seg;
ruta = #"C:\inetpub\wwwroot\WsDesarrollo2\" + #"XML" + #"\Empresa_" + name + #"\Flujo_" + flow + #"\Año_" + year + #"\Mes_" + month + #"\Dia_" + day + #"\";
existe = verifyDir(ruta);
if (existe == 0)
{
Directory.CreateDirectory(ruta);
}
fileName = "" + ruta + transaction + "_" + method + "_" + time;
datos[0] = ruta;
datos[1] = fileName;
return datos;
}
public void createXML<T>(string fileName, string route, T objeto)
{
System.Xml.Serialization.XmlSerializer serializador = new System.Xml.Serialization.XmlSerializer(typeof(T));
TextWriter tw = new StreamWriter(#"" + route + #"\" + fileName + ".xml");
serializador.Serialize(tw, objeto);
}

Ok guys, i solved this issue and im just comming to post the final result, just in case anyone needs it, this is the final code where i créate a directory, or validate if it already exists and then créate an XML for any tipe of object that goes in or out of a webservice, so this is the library:
public class xmlLog
{
public int verifyDir(string dir)
{
bool tryDir;
tryDir = Directory.Exists(dir);
if (tryDir == false)
{
return 0;
}
else
{
return 1;
}
}
public string[] createDir(string flow, int enclosure, string transaction, string method)
{
DateTime Hoy = DateTime.Now;
libs.Catalogos objCatalogos = new libs.Catalogos();
string day, month, year, hora, min, seg, time, ruta, fileName, name;
string[] datos = new string[2];
int existe;
name = objCatalogos.convertRecinto(enclosure);
day = System.DateTime.Now.ToString("dd");
month = System.DateTime.Now.ToString("MM");
year = System.DateTime.Now.ToString("yyyy");
hora = System.DateTime.Now.ToString("HH");
min = System.DateTime.Now.ToString("mm");
seg = System.DateTime.Now.ToString("ss");
time = hora + "_" + min + "_" + seg;
ruta = #"C:\inetpub\wwwroot\WsDesarrollo\" + #"XML" + #"\Empresa_" + name + #"\Flujo_" + flow + #"\Año_" + year + #"\Mes_" + month + #"\Dia_" + day + #"\";
existe = verifyDir(ruta);
if (existe == 0)
{
Directory.CreateDirectory(ruta);
}
fileName = "" + ruta + transaction + "_" + method + "_" + time;
datos[0] = ruta;
datos[1] = fileName;
return datos;
}
public void createXML<T>(string route, string fileName, T objeto)
{
string file = Path.Combine(route, fileName + ".xml");
System.Xml.Serialization.XmlSerializer slzr = new System.Xml.Serialization.XmlSerializer(typeof(T));
TextWriter tw = new StreamWriter(file);
slzr.Serialize(tw, objeto);
}
}
At the end of all this mess i managed to create a new directory and create an XML with just 2 code lines every time i need them, wich are the following ones:
string[] = objXML.createDir("IN", Convert.ToInt32(recinto), M903In.transaccionAduana, "903");
objXML.createXML(paramXML[0], paramXML[1], M903In);
I know this wont work for everyone, but this is the way i managed to work with to creade dinamy routes and filenames for XML documents on a webservice.
Hopefully it helps someone :3

Related

c# Windows Form, replace string in textbox (file content) with another string

I have a textbox that contains all of the lines of a loaded file.
It looks like this:
I am able to load a specific line of the file that contains a specific string using this in the app:
How would I be able to update the file/main textbox after I press the "Edit Module" button, if any of the textboxes would be changed .
For example, I would change Exam Weighting: "0.4" to Exam Weighting: "0.6", then press the "Edit Module" button which would edit the main textbox(file content). Which then would allow me to save the file with the updated content.
This is the code I am using to get a specific line from the file based on string from a textbox:
private void editModuleButton_Click(object sender, EventArgs e)
{
citation = editModuleComboBox.Text;
citationChange();
}
private void citationChange()
{
List<string> matchedList = new List<string>();
string[] linesArr = File.ReadAllLines(fileName);
//find matches
foreach (string s in linesArr)
{
if (s.Contains(citation))
{
matchedList.Add(s); //matched
}
}
//output
foreach (string s in matchedList)
{
string citationLine = s;
string[] lineData = citationLine.Split(',');
selectedModuleLabel.Text = lineData[2];
moduleTitleTextBox.Text = lineData[3];
creditsTextBox.Text = lineData[4];
semesterTextBox.Text = lineData[5];
examWeightingTextBox.Text = lineData[6];
examMarkTextBox.Text = lineData[7];
testWeightingTextBox.Text = lineData[8];
testMarkTextBox.Text = lineData[9];
courseworkWeightingTextBox.Text = lineData[10];
courseworkMarkTexbox.Text = lineData[11];
}
}
If somebody with enough rep could insert the images to this post, that would be great. Thanks
This solution might not be the perfect, but should work for you. What you need to do is whenever the Edit Module button is pressed, create a new string based on the text fields and replace it with the original line. First declare a string variable private string ChangedString = ""; inside the class, then:
foreach (string s in matchedList)
{
string citationLine = s;
string[] lineData = citationLine.Split(',');
string Stream = lineData[0]; //Store this somewhere so that it can be accessed later
string Stage = lineData[1]; //Store this somewhere so that it can be accessed later
selectedModuleLabel.Text = lineData[2];
moduleTitleTextBox.Text = lineData[3];
creditsTextBox.Text = lineData[4];
semesterTextBox.Text = lineData[5];
examWeightingTextBox.Text = lineData[6];
examMarkTextBox.Text = lineData[7];
testWeightingTextBox.Text = lineData[8];
testMarkTextBox.Text = lineData[9];
courseworkWeightingTextBox.Text = lineData[10];
courseworkMarkTexbox.Text = lineData[11];
}
store Stream and Stage in any Textbox/ComboBox if you already haven't then replace them accordingly in the following line. Now in EditButton_Click [Click Event] write:
ChangedString = Stream + "," + Stage + "," + selectedModuleLabel.Text + "," + moduleTitleTextBox.Text
+ "," + creditsTextBox.Text + "," + semesterTextBox.Text + "," + examWeightingTextBox.Text + ","
+ examMarkTextBox.Text + "," + courseworkWeightingTextBox.Text + "," + courseworkMarkTexbox.Text;
Now replace this string with the original line.
Edit: As you would get the line number which is being edited, store it in a variable, let's say
int LineBeingEdited = 3 //Supposing line number three is being edited.
Then again in the same Click event you can write this:
ChangedString = Stream + "," + Stage + "," + selectedModuleLabel.Text + "," + moduleTitleTextBox.Text
+ "," + creditsTextBox.Text + "," + semesterTextBox.Text + "," + examWeightingTextBox.Text + ","
+ examMarkTextBox.Text + "," + courseworkWeightingTextBox.Text + "," + courseworkMarkTexbox.Text;
var lines = TextBox1.Lines;
lines[LineBeingEdited] = ChangedString;
TextBox1.Lines = lines;
EDIT 2: To get the line number I would suggest you to modify your for each loop to for loop. Also add a int variable to store the line number inside the class like : private int LineBeingEdited = 0;
Modify this for each :
foreach (string s in linesArr)
{
if (s.Contains(citation))
{
matchedList.Add(s); //matched
}
}
To for loop:
for (int a = 0; a < linesArr.Length; a++)
{
if (s.Contains(citation))
{
matchedList.Add(linesArr[a]); //matched
LineBeingEdited = a;
break; //breaks the loop when a match is found
}
}
The above method is being used, taking into consideration that there will always be a single match. LineBeingEdited will now have the line number and can be accessed from anywhere in the class

How to append text to an existing text file?

I wrote an application that would ask the user for some details of the hotel that they are staying at, and the text does luckily get added, but if I add another person it will override the previous data that was in the file already. However, I want it to keep all of the data inputs.
Here is my code:
hotelName = txt_HotelName.Text;
ratings = txt_HotelRating.Text;
roomsNeeded = txt_RoomsNeeded.Text;
name = txt_UserName.Text;
surname = txt_UserLastname.Text;
contactDetails = txt_ContactDetail.Text;
paymentDetails = txt_PaymentMehthod.Text;
paymentDate = txt_PaymentDate.Text;
using (StreamWriter sw = new StreamWriter("HotelDocument.txt"))
{
sw.WriteLine(txt_HotelName + Environment.NewLine + txt_HotelRating + Environment.NewLine + txt_RoomsNeeded +
Environment.NewLine + txt_UserName + Environment.NewLine + txt_UserLastname + Environment.NewLine + txt_ContactDetail +
Environment.NewLine + txt_PaymentMehthod + Environment.NewLine + txt_PaymentDate);
}
MessageBox.Show($"Thank you for using our system {txt_UserName.Text}.", "Thank you", MessageBoxButtons.OK);
So what I want is to collect all of the data, rather than having them over-write each time.
Try appending the file:
string line = string.Join(Environment.NewLine, new string[] {
ratings,
roomsNeeded,
name,
surname,
contactDetails,
paymentDetails,
paymentDate});
File.AppendAllLines("HotelDocument.txt", new string[] {line});
Edit: if you want to organize the input data, I suggest using string interpolation (C# 6.0) or formatting:
string line = string.Join(Environment.NewLine, new string[] {
$"Ratings: {ratings}",
$"Rooms need: {roomsNeeded}",
$"Name: {name}",
$"Surname: {surname}",
$"Details: {contactDetails}",
$"Payment: {paymentDetails}",
$"Payment Date: {paymentDate}");
You need to specify a unique name:
using (StreamWriter sw = new StreamWriter("HotelDocument.txt"))
So instead of "HotelDocument.txt" maybe use the current DateTime, or even a new Guid() to be 100% unique. So something like:
var uniqueFileName = new Guid().ToString() + ".txt";
using (StreamWriter sw = new StreamWriter(uniqueFileName))
Or are you looking to append new data within the existing HotelDocument.txt?

Automatically create folders if does not exists in C#

So, I am trying to create a file at a specific path but the code I have doesn't allows me to create folders.
This is the code I have:
public void LogFiles()
{
string data = string.Format("LogCarga-{0:yyyy-MM-dd_hh-mm-ss}.txt", DateTime.Now);
for (int linhas = 0; linhas < dataGridView1.Rows.Count; linhas++)
{
if (dataGridView1.Rows[linhas].Cells[8].Value.ToString().Trim() != "M")
{
var pathWithEnv = #"%USERPROFILE%\AppData\Local\Cargas - Amostras\_logs\";
var filePath = Environment.ExpandEnvironmentVariables(pathWithEnv);
using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate))
{
using (StreamWriter writer = File.AppendText(filePath + data))
{
string carga = dataGridView1.Rows[linhas].Cells[0].Value.ToString();
string referencia = dataGridView1.Rows[linhas].Cells[1].Value.ToString();
string quantidade = dataGridView1.Rows[linhas].Cells[2].Value.ToString();
string dataemissao = dataGridView1.Rows[linhas].Cells[3].Value.ToString();
string linha = dataGridView1.Rows[linhas].Cells[4].Value.ToString();
string marca = dataGridView1.Rows[linhas].Cells[5].Value.ToString().Trim();
string descricaoweb = dataGridView1.Rows[linhas].Cells[6].Value.ToString().Trim();
string codprod = dataGridView1.Rows[linhas].Cells[7].Value.ToString().Trim();
string tipoemb = dataGridView1.Rows[linhas].Cells[8].Value.ToString().Trim();
string nomepc = System.Environment.MachineName;
writer.WriteLine(carga + ", " + referencia + ", " + quantidade + ", " + dataemissao + ", " + linha + ", " + marca + ", " + descricaoweb + ", " + codprod + ", "
+ tipoemb + ", " + nomepc);
}
}
}
}
}
This %USERPROFILE%\AppData\Local\ in the universal path and I want to automatically create the \Cargas - Amostras\_logs\.
Do you have any idea how to do it?
The simpelest solution is replace
using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate))
with
System.IO.Directory.CreateDirectory(filePath)
That will create the directory if it does not exist or do nothing if it does.
You need to create two checks, for your first folder and then second directory.
var pathWithEnv = #"%USERPROFILE%\AppData\Local\Cargas - Amostras\";
if (System.IO.Directory.Exists(pathWithEnv))
{
pathWithEnv = System.IO.Path.Combine(pathWithEnv, #"_logs\");
if (System.IO.Directory.Exists(pathWithEnv))
{
//Do what you want to do, both directories are found.
}
else
{
System.IO.Directory.CreateDirectory(pathWithEnv);
//Do what you want to do, both directories are available.
}
}
else
{
System.IO.Directory.CreateDirectory(pathWithEnv);
pathWithEnv = System.IO.Path.Combine(pathWithEnv, #"_logs\");
if (System.IO.Directory.Exists(pathWithEnv))
{
//Do what you want to do, both directories are available now.
}
else
{
System.IO.Directory.CreateDirectory(pathWithEnv);
//Do what you want to do, both directories are created.
}
}

Need Help the best overloaded method match for 'string.endswith(string)' has some invalid arguments

dynamic counter = 1;
string FileNameWithoutExtestion = "";
FileNameWithoutExtestion = file.Split('.')[0];
string FileExtestion = file.Split('.')[1];
while (System.IO.File.Exists(Dir + file))
{
if (true)
{
counter = counter + 1;
if (FileNameWithoutExtestion.EndsWith('_'))
{
file = FileNameWithoutExtestion + counter.ToString() + "." + FileExtestion;
}
else
{
file = FileNameWithoutExtestion + "_" + counter.ToString() + "." + FileExtestion;
}
}
}
if (FileNameWithoutExtestion.EndsWith('_')) //the error occurred here
Whats wrong ?
String.EndsWith() only has overloads with string as parameter, you insert a char.
Replace
.EndsWith('_')
with
.EndsWith("_")
and i would use those path-methods to parse filenames and extensions
string FileNameWithoutExtestion = System.IO.Path.GetFileNameWithoutExtension(file);
string FileExtestion = System.IO.Path.GetExtension(file); //.jpg
because FileNameWithoutExtestion = file.Split('.')[0]; will lead to a invalid value in case of a filename like foo.bar.jpg

How to keep logs in C#?

This is a WinForm written in C#.
Lets say I'm generating a random named text file in my selected directory. When the button is clicked teh first time, i write the data contained in the textboxes into that text file. If the user wants to do the same thing with different data in the textboxes then the click on the button should write the new data into the text file without losing the old data. It's like keeping logs, is this possible?
My code is like:
private readonly Random setere = new Random();
private const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private string RandomString()
{
char[] buffer = new char[5];
for (int i = 0; i < 5; i++)
{
buffer[i] = chars[setere.Next(chars.Length)];
}
return new string(buffer);
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult dia = MessageBox.Show("Wanna continue?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dia == DialogResult.Yes)
{
StreamWriter wFile = new StreamWriter("C:\\Users\\Ece\\Documents\\Testings\\" + RandomString() + ".txt");
wFile.WriteLine("Name Surname:" + text1.Text + text2.Text);
wFile.WriteLine("Other:" + text3.Text + text4.Text);
wFile.WriteLine("Money:" + textBox1.Text + " TL.");
wFile.WriteLine("*************************************");
wFile.Close();
}
else
{
return;
}
}
You can append to the text in the file.
See
File.AppendText
using (StreamWriter sw = File.AppendText(pathofFile))
{
sw.WriteLine("This");
sw.WriteLine("is Extra");
sw.WriteLine("Text");
}
where pathofFile is the path to the file to append to.
Have a look at using something like this:
StreamWriter fw = new StreamWriter(#"C:\Logs\MyFile.txt",true);
fw.WriteLine("Some Message" + Environment.Newline);
fw.Flush();
fw.Close();
Hope that helps. See MSDN StreamWriter for more information
Updated: Removed old example
Also if you are trying to create a unique file you can use Path.GetRandomFileName()
Again from the MSDN Books:
The GetRandomFileName method returns a
cryptographically strong, random
string that can be used as either a
folder name or a file name.
UPDATED: Added a Logger class example below
Add a new class to your project and add the following lines (this is 3.0 type syntax so you may have to adjust if creating a 2.0 version)
using System;
using System.IO;
namespace LogProvider
{
//
// Example Logger Class
//
public class Logging
{
public static string LogDir { get; set; }
public static string LogFile { get; set; }
private static readonly Random setere = new Random();
private const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public Logging() {
LogDir = null;
LogFile = null;
}
public static string RandomFileName()
{
char[] buffer = new char[5];
for (int i = 0; i < 5; i++)
{
buffer[i] = chars[setere.Next(chars.Length)];
}
return new string(buffer);
}
public static void AddLog(String msg)
{
String tstamp = Convert.ToString(DateTime.Now.Day) + "/" +
Convert.ToString(DateTime.Now.Month) + "/" +
Convert.ToString(DateTime.Now.Year) + " " +
Convert.ToString(DateTime.Now.Hour) + ":" +
Convert.ToString(DateTime.Now.Minute) + ":" +
Convert.ToString(DateTime.Now.Second);
if(LogDir == null || LogFile == null)
{
throw new ArgumentException("Null arguments supplied");
}
String logFile = LogDir + "\\" + LogFile;
String rmsg = tstamp + "," + msg;
StreamWriter sw = new StreamWriter(logFile, true);
sw.WriteLine(rmsg);
sw.Flush();
sw.Close();
}
}
}
Add this to your forms onload event
LogProvider.Logging.LogDir = "C:\\Users\\Ece\\Documents\\Testings";
LogProvider.Logging.LogFile = LogProvider.Logging.RandomFileName();
Now adjust your button click event to be like the following:
DialogResult dia = MessageBox.Show("Wanna continue?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dia == DialogResult.Yes)
{
StringBuilder logMsg = new StringBuilder();
logMsg.Append("Name Surname:" + text1.Text + text2.Text + Environment.NewLine);
logMsg.Append("Other:" + text3.Text + text4.Text + Environment.NewLine);
logMsg.Append("Money:" + textBox1.Text + " TL." + Environment.NewLine);
logMsg.Append("*************************************" + Environment.NewLine);
LogProvider.Logging.AddLog(logMsg.ToString());
} else
{
return;
}
Now you should only create one file for the entire time that application is running and will log to that one file every time you click your button.
You might want to take a look at log4net and the RollingFileAppender
Sure. Just open the file for appending with something like System.IO.File.AppendText

Categories