easiest way to add title row to log file - c#

Easiest way that I can add a title row to each of these files. I can't put it in the Log()'s because it would add the title row each time I reference the test.Log()'s
I thought about referencing 3 new int fields and each time I reference a Log1/2/3() it checks the value of the int and if it's 1 then add the title column else don't.I did one below but it seems redundant I figured there must be a better way.
public class Test
{
public static string File1 = DateTime.Now.ToString("yyyy-MM-dd") + "test1.csv";
public static int a = 0;
public static string File2 = DateTime.Now.ToString("yyyy-MM-dd") + "test2.csv";
public static string File3 = DateTime.Now.ToString("yyyy-MM-dd") + "test3.csv";
private static object _lockObj = new Object();
public static void Log1(string error, string record)
{ a++;
if(a==1){
lock (_lockObj)
{
File.AppendAllText(test.File1, "ERROR" + Environment.NewLine)
File.AppendAllText(test.File1, error + "," + record + Environment.NewLine);
}
}
else{
File.AppendAllText(test.File1, error + "," + record + Environment.NewLine);
}
}
public static void Log2(string message)
{
lock (_lockObj)
{
File.AppendAllText(test.File2, message + Environment.NewLine);
}
}
public static void Log3(Test c)
{
lock (_lockObj)
{
File.AppendAllText(test.File3, c + Environment.NewLine);
}
}
}

You may create a class like this:-
public class HeaderOnceAppender : RollingFileAppender
{
protected override void WriteHeader()
{
if (LockingModel.AcquireLock().Length == 0)
{
base.WriteHeader();
}
}

If you want put a Title row at the top of the file when creating it...
if(!System.IO.File.Exists(test.File1)) //if the file doesn't exist
{ //insert your header at the top
File.AppendAllText(test.File1,"My Header Line")
}
This will only append once when the file is first created

Related

How to get rid of namespace.Classname on call of display()?

Is there a way to get rid of practise.AcademicProgram in the output when the display() is called for an object initialized by the parameterized constructor. In my code below this occurs when s2.Display(); is executed.
Below is my working code for the same:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace practise
{
public class AcademicProgram
{
//Memnber variables
private int programCode;
private string programName;
private int programCredits;
//Properties for reading and writting the values of private fields
public int ProgramCode { get => programCode; set => programCode = value; }
public string ProgramName { get => programName; set => programName = value; }
public int ProgramCredits { get => programCredits; set => programCredits = value; }
//Default Constructor
public AcademicProgram()
{
}
//Parameterized Constructor
public AcademicProgram (int programCode, string programName, int programCredits)
{
this.programCode = programCode;
this.programName = programName;
this.programCredits = programCredits;
}
public void DisplayResults()
{
Console.WriteLine("Program Code: {0}\nProgram Name: {1}\nProgram Credits: {2}\n", programCode, programName, programCredits);
Console.WriteLine();
}
}
public class Instructor
{
//Member variables
public string forename;
public string surname;
public int identificationNumber;
public AcademicProgram academicProgram;
//Default Constructor
public Instructor()
{
this.forename = string.Empty;
this.surname = string.Empty;
this.identificationNumber = 0;
this.academicProgram = null;
}
//Parameterized Constructor
public Instructor(string forename, string surname, int identificationNumber, AcademicProgram academicProgram)
{
this.forename = forename;
this.surname = surname;
this.identificationNumber = identificationNumber;
this.academicProgram = academicProgram;
}
// Member Function to display values of member variables on Console.
public void Display()
{
Console.WriteLine(this.forename + ", " + this.surname + ", " + this.identificationNumber + ", " + this.academicProgram);
Console.WriteLine();
}
//Driver function
static void Main(string[] args)
{
//Instantiating object to call non-static member method
Instructor p = new Instructor();
p.Go();
Console.ReadKey();
}
//Non-static Member function
public void Go()
{
//Instantiating object without passing any values on runtime.
Instructor s = new Instructor();
//Instantiating object of AcademicProgram class without passing any values on runtime.
AcademicProgram progName = new AcademicProgram ();
//Set the values of fields using properties
progName.ProgramCode = 8230;
progName.ProgramName = "Systems Development: Cocnepts and Analysis";
progName.ProgramCredits = 4;
// Instantiating object while providing values on runtime.
Instructor s2 = new Instructor("Eddie ", "Jessup", 2394589, progName);
//Call to display method
s.Display();
s2.Display();
progName.DisplayResults();
}
}
}
Which gives an output shown here
Aside from override ToString(), I was able to fix it by a simple fix in display() of Instructor class as below:
public void Display()
{
Console.WriteLine(this.forename + ", " + this.surname + ", " + this.identificationNumber + ", " + this.academicProgram.ProgramCode + ", " + this.academicProgram.ProgramName + ", " + this.academicProgram.ProgramCredits);
Console.WriteLine();
}

How can i ZipFile.CreateFromDirectory with Log.txt in c#

My code:
public static string Source = #"\\192.168.181.1\Z$\z";
public static string Destination = #"\\192.168.181.1\Z$\z_rar\" + DateTime.Now.ToString("dddd");
public static string Extension = #".zip";
private static void Main(string[] args)
{
if (File.Exists(Destination + Extension))
try
{
File.Delete(Destination + Extension);
ZipFile.CreateFromDirectory(Source, Destination + Extension, CompressionLevel.NoCompression, false);
// here: zipped file details in txt file
}
catch (IOException e)
{
Console.WriteLine(e.Message);
}
else
ZipFile.CreateFromDirectory(Source, Destination + Extension, CompressionLevel.NoCompression, false);
}
How can i create zipped files details save to zipfilename_log.txt file (line by line) in same directory after zipfile.createfromdirectory ?
I solved the problem with the below code:
public static string Source = #"\\192.168.1.11\Z$\z";
public static string Destination = #"\\192.168.1.11\Z$\z_rar\";
public static string NameFormat = DateTime.Now.ToString("dddd");
public static string Extension = #".zip";
public static string LogFilePath = Destination + NameFormat + "_log.txt";
private static void Main(string[] args)
{
File.Delete(Destination + NameFormat + Extension);
File.Delete(LogFilePath);
try
{
ZipFile.CreateFromDirectory(Source, Destination + NameFormat + Extension,
CompressionLevel.NoCompression, false);
var fileListBuilder = new StringBuilder();
using (var za = ZipFile.OpenRead(Destination + NameFormat + Extension))
{
foreach (var zae in za.Entries) fileListBuilder.AppendLine(zae.FullName);
}
File.WriteAllText(LogFilePath, fileListBuilder.ToString());
}
catch (IOException e)
{
File.WriteAllText(LogFilePath, e.ToString());
}
}
Output:
file1.exe
file5.exe
Folder1
Folder2\file3.pdf
Folder2\file4.msi
Thanks to everyone who replies.

"InvalidCastException: Cannot cast from source type to destination type." when loading serialized data

I'd sincerely appreciate if you looked through some of my code as I can't seem to be able to fix it myself, and this will also hopefully help others understand serialization better.
I have four pieces of related code here, with anything seemingly irrelevant cut out. I'm trying to create a user profile in a set up where the user then chooses from a range of games to play. Only options/settings for the chosen games, in this case something to do with a fish, are saved.
The error in the title occurs in the 4th section [feel free to skip to that] which is the OptionsController.LoadOptions() function at
FishData.Store data = (FishData.Store)bf.Deserialize(fileOpt);
I have this at the top of all following sections:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
1) Profile data structure:
public class Profile { //Profile variables
public static string id;
public static string name;
public static string dob;
public static bool fishEnabled;
public static bool birdEnabled;
public static string stringTest;
[System.Serializable]
public class Store { //Profile variables
public string id;
public string name;
public string dob;
public bool fishEnabled;
public bool birdEnabled;
public string stringTest;
}
}
2) Fish data structure:
public class FishData { //static Fish variables to be used in game
public static bool sizeInc;
public static bool speedInc;
public static int level;
public static bool toxic;
public static bool handLeft;
public static bool timer;
public static int timerVal;
public static int percentReq;
public static int successReq;
public static string testStringTwo;
public static List<StatController.Session> sessions = new List<StatController.Session>();
[System.Serializable]
public class Store { //non static variable set for serialization
public bool sizeInc;
public bool speedInc;
public int level;
public bool toxic;
public bool handLeft;
public bool timer;
public int timerVal;
public int percentReq;
public int successReq;
public string testStringTwo;
public List<StatController.Session> sessions = new List<StatController.Session>();
}
}
3) The script where the data file was initially created and where there didn't seem to be problems:
public class ProfileController : MonoBehaviour {
public static string currentID;
//create ----
public InputField idField;
public InputField nameField;
public InputField dobField;
public Toggle fishToggle;
public Toggle birdToggle;
//open ------
public Button idTitleButton;
public Text nameText;
public Text dobText;
public Text testText;
public InputField numField;
void Save() { //saves new ID and declares required variables based on game choice
Debug.Log("id =" + idField.text + ", name = " + nameField.text + ", save");
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/" + idField.text + ".dat");
Profile.Store data = new Profile.Store(); //sets Profile variables
currentID = idField.text;
data.id = idField.text;
data.name = nameField.text;
data.dob = dobField.text;
data.fishEnabled = fishToggle.isOn;
data.birdEnabled = birdToggle.isOn;
Profile.id = idField.text;
Profile.name = nameField.text;
Profile.dob = dobField.text;
Profile.fishEnabled = fishToggle.isOn;
Profile.birdEnabled = birdToggle.isOn;
bf.Serialize(file, data); //saves Profile variables
if (fishToggle.isOn) {
FishData.Store dataFish = new FishData.Store(); //sets default Fish variables
dataFish.sizeInc = false;
dataFish.speedInc = false;
dataFish.level = 5;
dataFish.toxic = true;
dataFish.handLeft = false;
dataFish.timer = false;
dataFish.timerVal = 240;
dataFish.percentReq = 0;
dataFish.successReq = 0;
bf.Serialize(file, dataFish); //saves default Fish variables
Debug.Log("level = " + dataFish.level);
}
file.Close(); //closes save file
idSelectField.text = idField.text; //ensures current ID is used as selected ID where needed
EnableOpenProfile(); //loads new profile
}
void Load() {
if (File.Exists(Application.persistentDataPath + "/" + idField.text + ".dat")) { //loads save file
currentID = idField.text;
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/" + idField.text + ".dat", FileMode.Open);
Profile.Store data = (Profile.Store)bf.Deserialize(file);
nameField.text = data.name; //loads saved Profile details and settings
fishToggle.isOn = data.fishEnabled;
birdToggle.isOn = data.birdEnabled;
fishPlayButton.enabled = data.fishEnabled;
birdPlayButton.enabled = data.birdEnabled;
FishData.Store dataFish = (FishData.Store)bf.Deserialize(file); //loads saved Fish settings
FishData.sizeInc = dataFish.sizeInc;
FishData.speedInc = dataFish.speedInc;
FishData.toxic = dataFish.toxic;
FishData.timer = dataFish.timer;
FishData.level = dataFish.level;
FishData.timerVal = dataFish.timerVal;
FishData.percentReq = dataFish.percentReq;
FishData.successReq = dataFish.successReq;
FishData.handLeft = dataFish.handLeft;
file.Close(); //closes save file
nameText.text = "Name : " + data.name + " ID : " + data.id; //displays profile details
dobText.text = "DOB : " + data.dob;
}
else return;
}
}
4) The main script that produces the error when trying to load what was saved in the previous script:
public class OptionsController : MonoBehaviour {
public static bool handLeft = false;
public Toggle sizeIncToggle;
public Toggle speedIncToggle;
public Toggle toxicToggle;
public Toggle timerToggle;
public Toggle leftToggle;
public Toggle rightToggle;
public InputField levelField;
public InputField timerValField;
public InputField percentReqField;
public InputField successReqField;
void LoadOptions() {
if (File.Exists(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat")) {
BinaryFormatter bf = new BinaryFormatter();
FileStream fileOpt = File.Open(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat", FileMode.Open);
FishData.Store data = (FishData.Store)bf.Deserialize(fileOpt); //[[ERROR HERE]]
sizeIncToggle.isOn = data.sizeInc;
speedIncToggle.isOn = data.speedInc;
toxicToggle.isOn = data.toxic;
timerToggle.isOn = data.timer;
levelField.text = data.level.ToString();
timerValField.text = data.timerVal.ToString();
percentReqField.text = data.percentReq.ToString();
successReqField.text = data.successReq.ToString();
fileOpt.Close();
}
}
public void SaveOptions() {
Debug.Log("name = " + ProfileController.currentID + ", save");
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat");
FishData.Store data = new FishData.Store();
data.sizeInc = FishData.sizeInc;
data.speedInc = FishData.speedInc;
data.toxic = FishData.toxic;
data.timer = FishData.timer;
data.level = FishData.level;
data.timerVal = FishData.timerVal;
data.percentReq = FishData.percentReq;
data.successReq = FishData.successReq;
data.handLeft = FishData.handLeft;
bf.Serialize(file, data);
Debug.Log("level = " + FishData.level);
file.Close();
}
}
Thank you.
To ensure you are serializing/deserializing in the correct order it is best that you create a "holding" class which contains both a Fish.Store variable and Profile.Store variable. If you serialize and deserilize in different orders you will run into issues like trying to deserialize a Fish.Store object to Profile.Store.
Try creating another class with public variables of Fish.Store and Profile.Store, like:
public class ExampleClass
{
public Fish.Store FishStore;
public Profile.Store ProfileStore;
public ExampleClass()
{
}
}
Then do:
ExampleClass example = new ExampleClass();
example.ProfileStore = data;
example.FishStore = dataFish;
//File Create stuff, etc
bf.Serialize(file, example);
//File close stuff, etc
And to deserialize:
ExampleClass e = (ExampleClass)bf.Deserialize(fileOpt);
data = e.ProfileStore;
dataFish = e.FishStore;
If you only wish to serialize/deserialize one class at a time, it is best practice to read/write to/from one file per serialized class.
Correct me if I'm wrong but it seems you first save Profile.Store
and then you save FishData.Store.
Then on the load you try to retreive the FishData.Store when the Profile.Store is first in the file.
(I'm assuming you use the load from script 4 and the save in script 3.)

Lucene.NET TokenStream.Next method disappeared

I have to update a project using Lucene.NET. It first time I meet this library, and I should update the references to a new version. So I did with Lucene references via a NuGet.
But actually I should in a way update some methods that disappeared in the new versions.
public abstract class AnalyzerView
{
public abstract string Name { get; }
public virtual string GetView(TokenStream tokenStream,out int numberOfTokens)
{
StringBuilder sb = new StringBuilder();
Token token = tokenStream.Next();
numberOfTokens = 0;
while (token != null)
{
numberOfTokens++;
sb.Append(GetTokenView(token));
token = tokenStream.Next();
}
return sb.ToString();
}
protected abstract string GetTokenView(Token token);
}
The documentation is not very clear for me. As I understood I should use something like
while (tokenStream.IncrementToken()) { ... }
but how to obtain that following token is a mystery for me.
I saw similar question on StackOverflow, but my problem is that I need to obtain a Token rather thatn a string, because I have some code that uses tokens, like this one:
public class TermWithOffsetsView : AnalyzerView {
public override string Name {
get { return "Terms With Offsets"; }
}
protected override string GetTokenView(Token token) {
return token.TermText() +
" Start: " + token.StartOffset().ToString().PadLeft(5) +
" End: " + token.EndOffset().ToString().PadLeft(5) +
"\r\n";
}
}
Finally, after some researches, implemented something like this:
public abstract class AnalyzerView
{
public abstract string Name { get; }
public virtual string GetView(TokenStream tokenStream,out int numberOfTokens)
{
StringBuilder sb = new StringBuilder();
numberOfTokens = 0;
while (tokenStream.IncrementToken())
{
numberOfTokens++;
sb.Append(GetTokenView(tokenStream));
}
return sb.ToString();
}
protected abstract string GetTokenView(TokenStream tokenStream);
}
with the derived class like this:
public class TermWithOffsetsView : AnalyzerView {
public override string Name {
get { return "Terms With Offsets"; }
}
protected override string GetTokenView(TokenStream tokenStream) {
ITermAttribute termAtt = tokenStream.AddAttribute<ITermAttribute>();
IOffsetAttribute offsetAtt=tokenStream.AddAttribute<IOffsetAttribute>();
return string.Format("{0} Start: {1} End: {2}{3}",
termAtt.Term,
offsetAtt.StartOffset.ToString().PadLeft(5),
offsetAtt.EndOffset.ToString().PadLeft(5),
Environment.NewLine);
}
}

Factory Initializer + Singleton

I wrote a non-static Generic class instantiator for my Abstract Factory design, and use Singleton approach to make sure that only 1 instance of the instantiator will be initialized for every client request.
public sealed class FactoryInstantiator<T> where T: class
{
private static readonly FactoryInstantiator<T> _instance = new Instantiator<T>();
public static FactoryInstantiator<T> Instance
{
get
{
_client = HttpContext.Current.Session["ClientCode"].ToString();
return _instance;
}
}
private static string _client;
private string _className;
private string _fullyQualifiedClassName;
private string _assemblyName;
private FactoryInstantiator() { }
public T CreateInstance()
{
string fullClassName = typeof(T).ToString();
string[] splitClassName = fullClassName.Split('.');
_className = splitClassName[2];
_assemblyName = splitClassName[0] + "." + _client + "." + splitClassName[1];
_fullyQualifiedClassName = _assemblyName + "." + _className;
return (T)Activator.CreateInstance(Type.GetType(_fullyQualifiedClassName + "," + _assemblyName));
}
}
I abstracted the the whole namespace for each Client
namespace InventorySuite.Factory.BusinessLogic
{
// abstract factory
public abstract class InvoiceFactory
{
public abstract void Set() { }
}
}
namespace InventorySuite.Client1.BusinessLogic
{
// concrete invoice class for Client1
public class Invoice : InvoiceFactory
{
public override void Set() { }
}
}
namespace InventorySuite.Client2.BusinessLogic
{
// concrete invoice class for Client2
public class Invoice : InvoiceFactory
{
public override void Set() { }
}
}
protected void Page_Load(object sender, EventArgs e)
{
InvoiceFactory clientInvoice;
Session.Add("ClientCode", "Client1");
clientInvoice = FactoryInstantiator<InvoiceFactory>.Instance.CreateInstance();
clientInvoice.Set();
Session["ClientCode"] = "Client2";
clientInvoice = FactoryInstantiator<InvoiceFactory>.Instance.CreateInstance();
clientInvoice.Set();
}
It works well and already tested it, but my question is about its efficiency/performance hit, since I use reflection here, and for the Singleton approach if it has multi-threading issues (afaik, the singleton instance will be shared in all clients). I will also appreciate any other approach on this. thanks
You will not have any multi-threading issue since you're creating a new instance every time.
About the performance. You can measure the time creating 100 instances:
long ini = Environment.TickCount;
for (int i = 0; i < 100; i++)
{
Session["ClientCode"] = "Client2";
clientInvoice = FactoryInstantiator<InvoiceFactory>.Instance.CreateInstance();
clientInvoice.Set();
}
long timeCreate100Instances = Environment.TickCount - ini;
Using reflection, the performance hit resides in loading the assembly. I think that in your case, the class you're loading is in the same dll, you you also will not experiment any performance issue.
In other case, you can cache the Assembly obejcts in a Hastable/Dictionary in your CreateInstance() method.
using Richard and Daniel suggestions, I was able to reduce the performance hit of reflection using Caching. I therefore conclude that Reflection really has huge performance issues.
public T CreateInstance()
{
string fullClassName = typeof(T).ToString();
string[] splitClassName = fullClassName.Split('.');
_className = splitClassName[2];
_assemblyName = splitClassName[0] + "." + _client + "." + splitClassName[1];
_fullyQualifiedClassName = _assemblyName + "." + _className;
// use caching
T obj;
if (HttpContext.Current.Cache[_fullyQualifiedClassName] == null)
{
obj = (T)Activator.CreateInstance(Type.GetType(_fullyQualifiedClassName + "," + _assemblyName));
HttpContext.Current.Cache.Insert(_fullyQualifiedClassName, obj, null, DateTime.Now.AddMinutes(1), TimeSpan.Zero);
}
else
{
obj = (T)HttpContext.Current.Cache[_fullyQualifiedClassName];
}
return obj;
}
protected void Page_Load(object sender, EventArgs e)
{
InvoiceFactory inv;
Stopwatch globalTimer = Stopwatch.StartNew();
//normal instantiation
globalTimer = Stopwatch.StartNew();
for (int x = 0; x <= 10000; x++)
inv = new InventorySuit.Client1.BusinessLogic.Invoice;
globalTimer.Stop();
Response.Write(globalTimer.ElapsedMilliseconds + "<BR>");
//result 0ms
// using singleton factory w/o caching
globalTimer = Stopwatch.StartNew();
for (int x = 0; x <= 10000; x++)
inv = new FactoryInstantiator<InvoiceFactory>().CreateInstance();
globalTimer.Stop();
Response.Write(globalTimer.ElapsedMilliseconds + "<BR>");
//result 129ms
// using singleton factory w/ caching
for (int x = 0; x <= 10000; x++)
inv = FactoryInstantiator<InvoiceFactory>.Instance.CreateInstance();
globalTimer.Stop();
Response.Write(globalTimer.ElapsedMilliseconds + "<BR>");
//result 21ms
}
Loading the assemblies in Session State to solve multi-threading issue.
public T CreateInstance()
{
string fullClassName = typeof(T).ToString();
string[] splitClassName = fullClassName.Split('.');
_className = splitClassName[2];
_assemblyName = splitClassName[0] + "." + _client + "." + splitClassName[1];
_fullyQualifiedClassName = _assemblyName + "." + _className;
T obj;
var assemblies = HttpContext.Current.Session["ASSEMBLIES"] as Dictionary<string, T>;
if (assemblies == null)
{
assemblies = new Dictionary<string, T>();
assemblies.Add(_fullyQualifiedClassName, null);
HttpContext.Current.Session.Add("ASSEMBLIES", assemblies);
}
obj = assemblies[_fullyQualifiedClassName] as T;
if (obj == null)
{
obj = (T)Activator.CreateInstance(Type.GetType(_fullyQualifiedClassName + "," + _assemblyName));
assemblies[_fullyQualifiedClassName] = obj;
}
return obj;
}

Categories