I'm getting an error with StreamWriter that the file is in use by another process, but I believe it may be down to the speed at which I'm writing the file or more specifically the speed of it being opened/closed.
The code is as follows:
public static void writeLog(string msg)
{
StreamWriter log;
string currentMonth = DateTime.Now.ToString("MMM");
string currentYear = DateTime.Now.ToString("yyyy");
string directoryName = currentMonth + "-" + currentYear;
if (!Directory.Exists(#"C:\AutoSkill\LogFiles\" + directoryName + #"\"))
{
Directory.CreateDirectory(#"C:\AutoSkill\LogFiles\" + directoryName + #"\");
}
DateTime dt = DateTime.Now;
string date = dt.ToString("dd-MM-yy");
if (!File.Exists(#"C:\AutoSkill\LogFiles\" + directoryName + #"\" + date + ".txt"))
{
log = new StreamWriter(#"C:\AutoSkill\LogFiles\" + directoryName + #"\" + date + ".txt");
}
else
{
log = File.AppendText(#"C:\AutoSkill\LogFiles\" + directoryName + #"\" + date + ".txt");
}
try
{
log.WriteLine(msg);
}
catch (Exception err)
{
Console.WriteLine("There was an error writing to the log file.");
Console.WriteLine(err.Message);
}
log.Close();
}
So I'm closing the log each time I'm done writing to it, but I'm writing all out my output from the console screen to the file to keep track of what actually happened; sometimes the lines are only a few milliseconds apart if the action that was taken was quick or just returned null.
Am i getting this error due to speed of writing to the file? Is there a better way to handle writing a log file?
Disregard this, I'm dumb.
I've not had this problem for the last 2 years, I'm getting the error because I'm writing to the same file from a different thread, which is where the overlap is.
The file actually is in use by another process, the same one just a different thread.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am trying to to write data to a log file but nothing gets written to the file.
Aim of the program is to run a continuous loop and keep looking for file, if file is valid, process it and move it. I am logging for any errors and items that are created.
Also, how can I make my log file access able while the loop is running so that I can see that values got appended.
static void Main(string[] args)
{
var logFile = File.Create(filePath + "\\log_" + DateTime.Today.ToString("MMMM") + ".txt").ToString();
while (true)
{
try
{
var moveTo = Directory.CreateDirectory(#"" + directoryPath + "Processed_" + DateTime.Today.ToString("MMMM"));
var files = Directory.GetFiles(filePath);
var todaysDate = DateTime.Now.Date;
var firstOfMonth = new DateTime(todaysDate.Year, todaysDate.Month, 1);
var monthEnd = firstOfMonth.AddMonths(1).AddDays(-1);
if (todaysDate == monthEnd)
{
File.Move(logFile, #"" + moveToNewPath + logFile);
}
foreach (var fileName in files)
{
if (fileName.Contains("myFile.csv"))
{
var fileValues = File.ReadAllLines(filePath + fileName.Substring(44)).Skip(1).Select(v => new myFile(v)).ToList();
foreach (var i in fileValues)
{
try
{
var jsonValues = ValueFromFile(i);
var response = UploadData(url, username, password, values);
this should be written to a log file ===> .File.AppendAllText(logFile, Environment.NewLine + DateTime.Now + "\t" + response);
}
catch (Exception exception)
{
File.AppendAllText(logFile, Environment.NewLine + DateTime.Now + "\t" + exception.Message.Replace("\n", " "));
}
}
File.Move(fileName, #"" + directoryPath + "\\" + moveTo + "\\" + "processedMyFile" + DateTime.Now.Date.ToString("MM-dd-yy") + ".csv");
}
}
}
catch (Exception exception)
{
File.AppendAllText(logFile, Environment.NewLine + DateTime.Now + "\t" + exception.Message.Replace("\n", " "));
}
}
}
Let's start with this line at the top of the program:
var logFile = File.Create(filePath + "\\log_" + DateTime.Today.ToString("MMMM") + ".txt").ToString();
I'm not sure what you're doing with that ToString() call hanging off the end. It almost certainly doesn't do what you think it does. But I really want to take a closer look at the documentation for the File.Create() method here. Specifically, this excerpt:
The FileStream object created by this method has a default FileShare value of None; no other process or code can access the created file until the original file handle is closed.
Uh oh. That means the File.AppendAllText() call later on will be out of luck. But let's look at the AppendAllText() documentation. Specifically this:
The method creates the file if it doesn’t exist
Meaning you can just remove the problem line at the top. You neither need nor want it. Or maybe you just want to create the file name there, like this:
var logFile = Path.Combine(filePath, "log_" + DateTime.Today.ToString("MMMM") + ".txt");
As a bonus, I'd explore changing this code to use System.Diagnostics.Trace in conjunction with FileTraceListener and maybe a ConsoleTraceListener attached.
static string moveToNewPath = "...";
static string filePath = "...";
static string logFormat = "\n{0:s}\t{1}";
static string logFile = "";
static string directoryPath = "...";
static void LogMessage(string FilePath, string Message)
{
File.AppendAllText(Path.Combine(filePath, logFile),
string.Format(logFormat, DateTime.Now, Message.Replace("\n", " ")));
}
static void Main(string[] args)
{
logFile = "log_" + DateTime.Today.ToString("MMMM") + ".txt";
//Rotate log file on last day of month
try
{
var todaysDate = DateTime.Now.Date;
var firstOfMonth = new DateTime(todaysDate.Year, todaysDate.Month, 1);
var monthEnd = firstOfMonth.AddMonths(1).AddDays(-1);
if (todaysDate == monthEnd)
{
File.Move(Path.Combe(filePath, logFile), Path.Combine(moveToNewPath, logFile));
}
}
catch (Exception ex)
{
LogMessage(ex.Message);
}
while (true)
{
// !!!!!!!!!!!!!!
//Log rotate code used to be here... but... you need something to be sure this only happens once per day.
// I STRONGLY suspect this code should be setup to run as
// a SCHEDULED TASK set to run once per day or maybe once per hour, rather than an always-on background program.
// !!!!!!!!!!!!!!!!
try
{
var moveTo = Path.Combine(directoryPath, "Processed_" + DateTime.Today.ToString("MMMM"));
Directory.CreateDirectory(moveTo);
var files = Directory.GetFiles(filePath).Where(f => f.EndsWith("myFile.csv"));
foreach (var fileName in files)
{
var fileValues = File.ReadAllLines(filePath + fileName.Substring(44)).Skip(1).Select(v => new myFile(v));
foreach (var i in fileValues)
{
try
{
var jsonValues = ValueFromFile(i);
var response = UploadData(url, username, password, jsonValues);
LogMessage(response);
}
catch (Exception ex)
{
LogMessage(ex.Message);
}
}
File.Move(fileName, Path.Combine(moveTo, "processedMyFile" + DateTime.Now.Date.ToString("MM-dd-yy") + ".csv"));
}
}
catch (Exception ex)
{
LogMessage(ex.Message);
}
}
}
i have a cloud database server like application on my computer that i'm hosting my game on. However, every time an user tries to save data i get an UnauthorizedAccessException.
Im running it by admin and i dont have any specias right in my folder so i have no idea what's the problem.
Here's my code:
public const string root = "D:/DATABASE/";
public static void WriteData(string playername, string type, string data)
{
if (!Directory.Exists("D:/DATABASE/" + playername))
{
Directory.CreateDirectory("D:/DATABASE/" + playername);
Directory.CreateDirectory("D:/DATABASE/" + playername + "/weapons");
}
if (type != "Weapon")
{
using (StreamWriter sw = new StreamWriter("D:/DATABASE/" + playername + "/" + type + ".sav"))
{
sw.WriteLine(data);
}
}
else
{
string[] dat = data.Split('%');
using (StreamWriter sw = new StreamWriter("D:/DATABASE/" + playername + "/weapons/" + dat[0] + ".gfa"))
{
string[] lines = dat[1].Split('#');
foreach (string cline in lines)
{
sw.WriteLine(cline);
}
}
}
}
public static string ReadLoadout(string playername)
{
string output = "";
string[] items = new string[2];
using (StreamReader sr = new StreamReader(root + playername + "/loadout.gfl"))
{
items[0] = sr.ReadLine();
items[1] = sr.ReadLine();
}
int c = 0;
foreach (string citem in items)
{
if (c > 0) output += "$";
output += citem + "%" + GetCompressedWeaponFile(playername, citem);
c++;
}
return output;
}
public static string GetCompressedWeaponFile(string playerName, string weaponName)
{
string output = "";
using (StreamReader sr = new StreamReader(root + playerName + "/weapons/" + weaponName))
{
string line = " ";
int c = 0;
while (line != null)
{
line = sr.ReadLine();
if (line != null)
{
if (c > 0) output += "#";
output += line;
}
c++;
}
}
return output;
}
public static void RegisterNewUser(string username, string password, string email)
{
string udir = root + username;
Directory.CreateDirectory(udir);
Directory.CreateDirectory(udir + "/weapons");
Directory.CreateDirectory(udir + "/loadouts");
File.WriteAllText(udir + "/password.sav", password);
File.WriteAllText(udir + "/level.sav", "1");
File.WriteAllText(udir + "/money.sav", "1000");
File.WriteAllText(udir + "/email.sav", email);
File.WriteAllText(udir + "/loadout.gfl", "");
using (StreamWriter sw = new StreamWriter(root + "emails.txt", true))
{
sw.WriteLine(email);
}
Email.Send(email, "New Account Registration", string.Format(mailTemplate, username, password));
}
public static void EditLoadout(string username, string items)
{
File.WriteAllLines(root + username + "/loadout.gfl",items.Split('#'));
}
It is difficult to provide specific help without more information. Here are a few of troubleshooting suggestions:
1) Try running your code on a different machine. Specifically your development computer. Do you still have the same error? If not, then there is indeed a permission problem.
2) Have you tried checking the stack trace of the exception?
When you run the application on your own computer, try using the IDE to display the exception. Yes, the problem may ultimately be in a low-level class, but you should be able to break on the error and go back in the call stack to see which method in your code is actually throwing the error.
3) Check the actual exception, even for a system-level exception.
Chances are, if you are able to debug this in the IDE, that you will see property information that will give you a hint. Is it in a directory method or a file write method? Check additional properties. Somewhere it might give you the text of the path (assuming it's a file issue) that it failed on that that could help narrow things down too.
4) Add Exception handling to your code
This is a good rule of thumb, and you should really do this anyway to make a stronger program. Regardless of who's method you are calling (yours, someone else's, or a system method) you need to determine where it should be handled.
For example, in your code, in the RegisterNewUser() method, consider something like:
public static void RegisterNewUser(string username, string password, string email)
{
try
{
string udir = root + username;
Directory.CreateDirectory(udir);
Directory.CreateDirectory(udir + "/weapons");
Directory.CreateDirectory(udir + "/loadouts");
File.WriteAllText(udir + "/password.sav", password);
File.WriteAllText(udir + "/level.sav", "1");
File.WriteAllText(udir + "/money.sav", "1000");
File.WriteAllText(udir + "/email.sav", email);
File.WriteAllText(udir + "/loadout.gfl", "");
using (StreamWriter sw = new StreamWriter(root + "emails.txt", true))
{
sw.WriteLine(email);
}
Email.Send(email, "New Account Registration", string.Format(mailTemplate, username, password));
}
catch (Exception ex)
{
// Create a method to display or log the exception, with it's own error handler
LogAndDisplayExceptions(ex);
// Send the user a message that we failed to add them. Put this in it's own try-catch block
// ideally, for readability, in it's own method.
try
{
Email.Send(email, "Failed to register", "An error occurred while trying to add your account.");
}
catch (Exception exNested)
{
LogAndDisplayExceptions(exNested);
}
}
}
5) Add a "crash-and-burn" exception handler to "main"
In the method that is your "top method" (it's hard to tell in the snippet you provided since there are few methods that would attempt to write to the disk) you could wrap your code in a try - catch block and print the exception or write it to disk.
If you have having trouble writing the exception to disk, I would suggest creating an error file first, make sure that the user account that is running the program can write to it, and then in the catch block open the file for APPEND. This should make it easier to get to the error text.
6) When all else fails, use the Debug class or Console class to write the traditional "I made it to line x."
While this will not solve your problem, it should help you get more information that will provide more insight into where your code is causing an error.
I have been doing this for a university project and have run into a problem. I have managed to load multiple lines from a file but I am unable to save them back to a file. I can save a single string to the file, which is the last string processed but that is it. I may be doing it completely wrong by performing a loop, but I cant think of any other way to do it. The coding for the savefile section is as follows:
case "s":
case "8":
{
int savecount = 0;
string savestring = "";
//Clear the text file ready to be saved
using (FileStream fs = File.Create("billing.txt"))
{
}
while (savecount != CustomerCount)
{
using (StreamWriter save = new StreamWriter("billing.txt"))
{
//Create the string to save to the file
savestring = CustomerNumber[savecount] + ","
+ CustomerName[savecount] + ","
+ Address[savecount] + ","
+ RateScheme[savecount] + ","
+ PeakKWH[savecount] + ","
+ OffPeakKWH[savecount] + ","
+ StandardKWH[savecount];
Console.WriteLine(savestring);
save.WriteLine(savestring);
savecount++;
Console.ReadLine();
}
}
Console.WriteLine("All data saved successfully");
Console.ReadLine();
break;
}
Not sure where to go from here. Any help would be appreciated
You should open the file for saving before the loop. E.g.
using (StreamWriter save = new StreamWriter("billing.txt")) {
while (savecount != CustomerCount) {
// rest of your code here
At the moment, you are opening the file in each loop, writing a line out. Then re-opening it (and losing the data already written).
As pointed out in the comments, you don't need to call File.Create. By default the StreamWriter will overwrite the existing file.
You need the while loop inside the using { } As it is you're overwriting your data each time, leaving the last item in your file when you look at it:
using (StreamWriter save = new StreamWriter("billing.txt"))
{
while (savecount != CustomerCount)
{
//Create the string to save to the file
string savestring = CustomerNumber[savecount] + ","
+ CustomerName[savecount] + ","
+ Address[savecount] + ","
+ RateScheme[savecount] + ","
+ PeakKWH[savecount] + ","
+ OffPeakKWH[savecount] + ","
+ StandardKWH[savecount];
Console.WriteLine(savestring);
save.WriteLine(savestring);
savecount++;
Console.ReadLine();
}
}
What You are doing wrong is, you are opening the file in each iteration of while, writing a line in file and Then again re-opening the file and overwriting the contents. You can rechange your code
using (StreamWriter save = new StreamWriter("billing.txt"))
{
while (savecount != CustomerCount)
{
// rest of string formation of saveString logic and save.WriteLine(savestring); goes here
.....
}
}
I think you can use a simple code also where you can save all your input string in an List and use File.WriteAllLines function as
{
....
List<string> Customers = new List<string>();
for (savecount = 0; savecount < CustomerCount; savecount++)
{
//Create the string to save to the file
Customers.Add( CustomerNumber[savecount] + "," + CustomerName[savecount] + "," + Address[savecount] + "," + RateScheme[savecount] + "," + PeakKWH[savecount] + "," + OffPeakKWH[savecount] + "," + StandardKWH[savecount]);
Console.WriteLine(Customers[savecount]);
}
string filePath = "billing.txt"; // This is your file path where all the contents are to be written
File.WriteAllLines(filePath, Customers);
..........
}
You need:
using (StreamWriter save = new StreamWriter("billing.txt")) {
while (savecount != CustomerCount) {
You have to open file before loop because opening inside deletes all previous data written in that, also it takes some time for opening.
However you can open file inside loop, but you need to set append file, it would be:
StreamWriter save = new StreamWriter("billing.txt", true)
This option is slower and you may need to clear file before opening in append mode, so it isn't the best option.
Can someone tell me what is going to happen in this code when an error is encountered? Ideally it should continue the foreach statement until it gets to the last record, but I suspect it's stopping in the middle of the operation because when I check the number of files moved it's off by 225. If it is in fact stopping because of an error, what can I do to make it continue the loop?
I'm creating a new upload manager for our software and need to clean the old files up. There are about 715 orphaned files equaling around 750 MB after a year and a half of use because the original developers didn't write the code to correctly overwrite old files when a new one was uploaded. They also saved the files in a single directory. I can't stand that so I'm moving all of the files into a structure - Vessel Name - ServiceRequesetID - files uploaded for that service. I'm also giving the users a gridview to view and delete files they no longer need as they work the service.
protected void Button1_Click(object sender, EventArgs e)
{
GridViewRow[] rowArray = new GridViewRow[gv_Files.Rows.Count];
gv_Files.Rows.CopyTo(rowArray, 0);
int i = -1;
foreach(GridViewRow row in rowArray)
{
i++;
string _serviceRequestID = ((Label)gv_Files.Rows[row.RowIndex].FindControl("lbl_SRID")).Text;
string _vesselName = ((Label)gv_Files.Rows[row.RowIndex].FindControl("lbl_VesselID")).Text;
string _uploadDIR = Server.MapPath("uploadedFiles");
string _vesselDIR = Server.MapPath("uploadedFiles" + "\\" + _vesselName);
string _fileName = ((Label)gv_Files.Rows[row.RowIndex].FindControl("lbl_FileName")).Text;
DirectoryInfo dInfo = new DirectoryInfo(_uploadDIR);
DirectoryInfo dVessel = new DirectoryInfo(_vesselDIR);
DirectoryInfo dSRID = new DirectoryInfo(_serviceRequestID);
dInfo.CreateSubdirectory(_vesselName);
dVessel.CreateSubdirectory(_serviceRequestID);
string _originalFile = _uploadDIR + "\\" + _fileName;
string _fileFullPath = Path.Combine(Server.MapPath("uploadedFiles/" + _vesselName + "/" + _serviceRequestID + "/"), _fileName);
FileInfo NewFile = new FileInfo(_fileFullPath);
string _fileUploadPath = _vesselName + "/" + _serviceRequestID + "/" + _fileName;
string sourceFile = _originalFile;
FileInfo _source = new FileInfo(sourceFile);
string destinationFile = _fileFullPath;
try
{
{
File.Move(sourceFile, destinationFile);
movefiles.InsertNewUploadPath(Convert.ToDecimal(_serviceRequestID), 1, _fileUploadPath);
}
}
catch (Exception ex)
{
CreateLogFiles Err = new CreateLogFiles();
Err.ErrorLog(Server.MapPath("Logs/ErrorLog"), ex.Message);
}
}
_utility.MessageBox("Completed processing files.");
}
As long as the error encountered occurs within the try catch clause, the code will continue executing within the foreach loop. However, if the error occurs outside of the try catch, the function will exit and throw an error. How many files does your error log report??
This is main program.cs
LogError.WriteError("Application started: " + DateTime.Now + Environment.NewLine);
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new CrawlerApp());
}
catch (Exception e)
{
LogError.WriteError(e);
}
LogError.WriteError("Application closed: " + DateTime.Now + Environment.NewLine);
and this is LogError class
public static class LogError
{
public static void WriteError(Exception e)
{
WriteError("Message: " + e.Message + Environment.NewLine + "Stack trace: " + e.StackTrace);
}
public static void WriteError(string error)
{
try
{
StreamWriter sw = File.AppendText("log.txt");
sw.WriteLine(DateTime.Now + Environment.NewLine);
sw.WriteLine(error + Environment.NewLine);
sw.WriteLine(Environment.NewLine);
sw.Close();
}
catch (Exception)
{
//
}
}
}
When i publish application and run it log.txt file is never created. If i run application from bin/debug folder then works. Why when i publish app logging not working. I am using win 2003 OS.
It could be an UnauthorizedAccessException.
Rather than guess at it you might want to change your catch to log to the event log rather than just swallowing it
File.AppendText only works if the file already exists: http://msdn.microsoft.com/en-us/library/system.io.file.appendtext.aspx. This link also has this sample code:
string path = #"c:\temp\MyTest.txt";
// This text is added only once to the file.
if (!File.Exists(path))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine("Hello");
sw.WriteLine("And");
sw.WriteLine("Welcome");
}
}
// This text is always added, making the file longer over time
// if it is not deleted.
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine("This");
sw.WriteLine("is Extra");
sw.WriteLine("Text");
}
you could use this code too, it works whether the file exits or not. As a plus it creates the log file based on the current DateTime in YYYYMMDD format
private static void doLog(String message)
{
//getting current date
String dateStr = "";
int day, month, year;
year = System.DateTime.Now.Year;
month = System.DateTime.Now.Month;
day = System.DateTime.Now.Day;
dateStr += year.ToString() + "";
if (month < 10) dateStr += "0";
dateStr += month.ToString() + "";
if (day < 10) dateStr += "0";
dateStr += day.ToString() + "";
//writting the message
string logFile = Environment.CurrentDirectory + #"/LOG_" + dateStr + #".txt";
System.IO.StreamWriter sw = new System.IO.StreamWriter(logFile, true);
sw.WriteLine(System.DateTime.Now.ToString() + "\t" + message);
sw.Close();
}
Your log-writing code is probably throwing an exception. Try removing the try/catch in WriteError to see what exception is being thrown.