Reputation: 1313
How would I write a log file in c#?
Currently i have a timer with this statement which ticks every 20 secs:
File.WriteAllText(filePath+"log.txt", log);
For everything that i want logged i do this:
log += "stringToBeLogged";
As you can assume the string log just grows and grows as the program runs. (I don't even know if there is a maximum chars per string?)
I assume that there must be better ways of doing this. i just thought that it would be heavy to write the whole file again and again for every time something is added to the log.
Upvotes: 72
Views: 517136
Reputation: 149
Opening and closing a file to append to it, isn't thread safe and it's not very efficient either. If two threads try to write to the same file at the same time, there will be an IOException.
I wrote a class back in the late 90's, upgraded it over time, then lost it back in 2010. I threw it back together from what I remembered after I lost it. It's still old code so could always use a major update, but it's an asynchronous text logger with multiple log types and files. It uses FileStream() to open files and holds the handle open. It puts new information into a another ListArray(). I did try Queue at one point, but List would most likely be better today. It uses AutoResetEvent to trip logging after message is passed in and passes that info down to write to file.
I would most likely use List today, but it's using ArrayList() to hold the file handles. This also blocks anything else from trying to access or modify the file while your using it.
Full class. http://chizl.com/dl/dev/csharp/FreeThread.csharp.txt
private struct FileHandles
{
public FileStream twHandle;
public String szFileName;
public decimal dwFileSize;
public String szRootFileName;
} //FileHandles
private struct TransLog
{
public String szBuffer;
public LOG_TYPE enumFileType;
public String AddedDateTime;
public bool bAddReturn;
public String szFileName;
} //TransLog
Happy hacking
Upvotes: 0
Reputation: 1
Above code will throw: Process can't access the file because it is being used by another process error because of File.Create(m_exePath + "\" + "log.txt"); if you will comment out this it will work as expected
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace SolutionLogWriter
{
public static class LogWriterClass
{
private static string m_exePath = string.Empty;
public static void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string fullpath = m_exePath + "\\" + "log.txt";
if (File.Exists(fullpath))
{
File.Delete(fullpath);
}
// File.Create(fullpath);
try
{
FileStream fs = new FileStream(fullpath, FileMode.OpenOrCreate);
using (StreamWriter w = new StreamWriter(fs))
AppendLog(logMessage, w);
}
catch (Exception ex)
{
AppendLog(ex.ToString());
}
}
private static void AppendLog(string logMessage, TextWriter txtWriter=null)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
txtWriter.Write(ex.Message);
}
}
}
}
Upvotes: 0
Reputation: 71
If your application is multithreaded then in some environments file.appendalltext could give error like file already in use and if you skip that then you could lose important logs . For that you can use Lock object technique with file.append.. in that case it will wait for existing process to close and the write your log
This can also save you from adding other libraries in your source
Upvotes: 0
Reputation: 509
as posted by @randymohan, with using statements instead
public static void WriteLog(string strLog)
{
string logFilePath = @"C:\Logs\Log-" + System.DateTime.Today.ToString("MM-dd-yyyy") + "." + "txt";
FileInfo logFileInfo = new FileInfo(logFilePath);
DirectoryInfo logDirInfo = new DirectoryInfo(logFileInfo.DirectoryName);
if (!logDirInfo.Exists) logDirInfo.Create();
using (FileStream fileStream = new FileStream(logFilePath, FileMode.Append))
{
using (StreamWriter log = new StreamWriter(fileStream))
{
log.WriteLine(strLog);
}
}
}
Upvotes: 14
Reputation: 2531
From the performance point of view your solution is not optimal. Every time you add another log entry with +=, the whole string is copied to another place in memory. I would recommend using StringBuilder instead:
StringBuilder sb = new StringBuilder();
...
sb.Append("log something");
...
// flush every 20 seconds as you do it
File.AppendAllText(filePath+"log.txt", sb.ToString());
sb.Clear();
By the way your timer event is probably executed on another thread. So you may want to use a mutex when accessing your sb
object.
Another thing to consider is what happens to the log entries that were added within the last 20 seconds of the execution. You probably want to flush your string to the file right before the app exits.
Upvotes: 80
Reputation: 1549
create a class create a object globally and call this
using System.IO;
using System.Reflection;
public class LogWriter
{
private string m_exePath = string.Empty;
public LogWriter(string logMessage)
{
LogWrite(logMessage);
}
public void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
try
{
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
{
Log(logMessage, w);
}
}
catch (Exception ex)
{
}
}
public void Log(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
}
}
}
Upvotes: 73
Reputation: 5321
Add log to file with Static Class
public static class LogWriter
{
private static string m_exePath = string.Empty;
public static void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (!File.Exists(m_exePath + "\\" + "log.txt"))
File.Create(m_exePath + "\\" + "log.txt");
try
{
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
AppendLog(logMessage, w);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void AppendLog(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
}
}
}
Upvotes: 7
Reputation: 657
public static void WriteLog(string strLog)
{
StreamWriter log;
FileStream fileStream = null;
DirectoryInfo logDirInfo = null;
FileInfo logFileInfo;
string logFilePath = "C:\\Logs\\";
logFilePath = logFilePath + "Log-" + System.DateTime.Today.ToString("MM-dd-yyyy") + "." + "txt";
logFileInfo = new FileInfo(logFilePath);
logDirInfo = new DirectoryInfo(logFileInfo.DirectoryName);
if (!logDirInfo.Exists) logDirInfo.Create();
if (!logFileInfo.Exists)
{
fileStream = logFileInfo.Create();
}
else
{
fileStream = new FileStream(logFilePath, FileMode.Append);
}
log = new StreamWriter(fileStream);
log.WriteLine(strLog);
log.Close();
}
Refer Link: blogspot.in
Upvotes: 18
Reputation: 1178
There are 2 easy ways
Upvotes: 1
Reputation: 48
This is add new string in the file
using (var file = new StreamWriter(filePath + "log.txt", true))
{
file.WriteLine(log);
file.Close();
}
Upvotes: 2
Reputation: 81
Very convenient tool for logging is http://logging.apache.org/log4net/
You can also make something of themselves less (more) powerful. You can use http://msdn.microsoft.com/ru-ru/library/system.io.filestream (v = vs.110). Aspx
Upvotes: 7
Reputation: 2210
if(!File.Exists(filename)) //No File? Create
{
fs = File.Create(filename);
fs.Close();
}
if(File.ReadAllBytes().Length >= 100*1024*1024) // (100mB) File to big? Create new
{
string filenamebase = "myLogFile"; //Insert the base form of the log file, the same as the 1st filename without .log at the end
if(filename.contains("-")) //Check if older log contained -x
{
int lognumber = Int32.Parse(filename.substring(filename.lastIndexOf("-")+1, filename.Length-4); //Get old number, Can cause exception if the last digits aren't numbers
lognumber++; //Increment lognumber by 1
filename = filenamebase + "-" + lognumber + ".log"; //Override filename
}
else
{
filename = filenamebase + "-1.log"; //Override filename
}
fs = File.Create(filename);
fs.Close();
}
Refer link:
http://www.codeproject.com/Questions/163337/How-to-write-in-log-Files-in-C
Upvotes: 4
Reputation: 6279
Use File.AppendAllText instead:
File.AppendAllText(filePath + "log.txt", log);
Upvotes: 27