Write text to file System.IO.IOException - c#

I have the following code to write some current positions down to a file :
while (onvifPTZ != null)
{
string[] lines = {"\t Act Value [" + curPan.ToString() +
"," + curTilt.ToString() +
"," + curZoom.ToString() + "]","\t Ref Value [" + newPTZRef.pan.ToString() +
"," + newPTZRef.tilt.ToString() +
"," + newPTZRef.zoom.ToString() + "]", "\t Dif Value [" + dPan.ToString() +
"," + dTilt.ToString() +
"," + dZoom.ToString() + "]" + Environment.NewLine };
string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
using (StreamWriter outputFile = new StreamWriter(Path.Combine(mydocpath, "WriteLines1.txt")))
{
foreach (string line in lines)
outputFile.WriteLine(line);
}
}
I have an error telling me that the process could not use the File at( path..) because its already in use. I tried restarting, and deleting the File( it actually worked one time) but nothing seems to work. Can I write it different so it works, and everytime I start it it makes a new file?
And another question is if somebody knows why it only saves one position...the position is renewed every few milliseconds and I want every position in that file, not only one..how am I supposed to do it?
Same thing works perfectly in the console, also giving the new positions every time, but not in the file.

You should either call StreamWriter.Flush() or set StreamWriter.AutoFlush = true
Additionally before or after writing, I usually check whether the file is locked by another process:
bool b = false;
while(!b)
{
b = IsFileReady(fileName)
}
...
/// <summary>
/// Checks if a file is ready
/// </summary>
/// <param name="sFilename"></param>
/// <returns></returns>
public static bool IsFileReady(string sFilename)
{
// If the file can be opened for exclusive access it means that the file
// is no longer locked by another process.
try
{
using (FileStream inputStream = File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.None))
{
return inputStream.Length > 0;
}
}
catch (Exception)
{
return false;
}
}

Related

C# Get files Outlook Attachments single-multiple selected files Win 7, Win 10

I have re-edited my question since the problem lies elsewhere.
I have this piece of code to drop the files from outlook (single or multiple) at specific win form. On windows 7 stations the copy is made, but on windows 10 cannot get the list of filename from class.
public class OutlookDataObject : System.Windows.Forms.IDataObject
Class shown on this post
This class is working on Working code for win 7 but no filename return on windwos 10. This huge class is way over my understanding.
There is a simple way to get from outlook the selected attachements to prepare them to drop ?
private void btn_Home_DragDrop(object sender, DragEventArgs e)
{
bool debug = true;
if (debug) { txt_FileInfo.AppendText("Entering drop method " + Environment.NewLine); }
folderBrowserDialog1.SelectedPath = LastSelectedFolder.GlobalVar;
if (debug)
{ txt_FileInfo.AppendText("Get last path " + Environment.NewLine); }
folderBrowserDialog1.Description = "Drop the files";
if (debug)
{ txt_FileInfo.AppendText("Show folder dialog " + Environment.NewLine); }
if (folderBrowserDialog1.ShowDialog() != DialogResult.OK)
{
return;
}
LastSelectedFolder.GlobalVar = folderBrowserDialog1.SelectedPath.ToString();
if (debug)
{ txt_FileInfo.AppendText("Path is selected " + LastSelectedFolder.GlobalVar + Environment.NewLine); }
string[] fileNames = null;
if (debug)
{ txt_FileInfo.AppendText("Prepare to transfer " + Environment.NewLine); }
if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
{
if (debug)
{ txt_FileInfo.AppendText("DataFormats.FileDrop " + Environment.NewLine); }
fileNames = (string[])e.Data.GetData(DataFormats.FileDrop);
foreach (string fileName in fileNames)
{
// do what you are going to do with each filename
string destinationFile = Path.Combine(folderBrowserDialog1.SelectedPath, Path.GetFileName(fileName));
if (debug)
{ txt_FileInfo.AppendText("Destination File " + destinationFile + Environment.NewLine); }
if (Operation.CopyFile(fileName, destinationFile, ci))
{
txt_FileInfo.AppendText("File have been copied to " + destinationFile + Environment.NewLine);
}
}
}
else if (e.Data.GetDataPresent("FileGroupDescriptor"))
{
if (debug)
{ txt_FileInfo.AppendText("FileGroupDescriptor " + Environment.NewLine); }
OutlookDataObject dataObject = new OutlookDataObject(e.Data);
string[] filenames = (string[])dataObject.GetData("FileGroupDescriptor");
for (int fileIndex = 0; fileIndex < filenames.Length; fileIndex++)
{
if (debug)
{ txt_FileInfo.AppendText("Files in attachement " + filenames[fileIndex] + Environment.NewLine); }
string path = Path.GetTempPath();
// put the zip file into the temp directory
string theFile = path + filenames[fileIndex].ToString();
// create the full-path name
if (debug)
{ txt_FileInfo.AppendText("Get temp Path " + theFile + Environment.NewLine); }
//
// Second step: we have the file name.
// Now we need to get the actual raw
// data for the attached file and copy it to disk so we work on it.
//
// get the actual raw file into memory
MemoryStream ms = (MemoryStream)e.Data.GetData(
"FileContents", true);
// allocate enough bytes to hold the raw data
byte[] fileBytes = new byte[ms.Length];
// set starting position at first byte and read in the raw data
ms.Position = 0;
ms.Read(fileBytes, 0, (int)ms.Length);
// create a file and save the raw zip file to it
FileStream fs = new FileStream(theFile, FileMode.Create);
fs.Write(fileBytes, 0, (int)fileBytes.Length);
fs.Close(); // close the file
FileInfo tempFile = new FileInfo(theFile);
// always good to make sure we actually created the file
if (tempFile.Exists == true)
{
// for now, just delete what we created
string fileName = tempFile.FullName;
string destinationFile = Path.Combine(folderBrowserDialog1.SelectedPath, Path.GetFileName(fileName));
if (debug)
{ txt_FileInfo.AppendText("destinationFile " + destinationFile + Environment.NewLine); }
if (debug)
{ txt_FileInfo.AppendText("Prepare to copy " + destinationFile + Environment.NewLine); }
if (Operation.CopyFile(fileName, destinationFile, ci))
{
txt_FileInfo.AppendText("File have been copied to " + destinationFile + Environment.NewLine);
}
else
{
if (debug)
{ txt_FileInfo.AppendText("Copy failed " + " Source " + fileName + " Destination " + destinationFile + Environment.NewLine); }
}
tempFile.Delete();
if (debug)
{ txt_FileInfo.AppendText("Delete temp file " + tempFile + Environment.NewLine); }
}
else
{ Trace.WriteLine("File was not created!"); }
// catch (Exception ex)
//{
// Trace.WriteLine("Error in DragDrop function: " + ex.Message);
// // don't use MessageBox here - Outlook or Explorer is waiting !
//}
}
}
}
I will replay here quote from here. For above class to work on win 8 + couple of line to be changed (from int to long)
from:
IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorWPointer + Marshal.SizeOf(fileGroupDescriptor.cItems));
to
IntPtr fileDescriptorPointer = (IntPtr)((long)fileGroupDescriptorWPointer + Marshal.SizeOf(fileGroupDescriptor.cItems));
from:
fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
to
fileDescriptorPointer = (IntPtr)((long)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
Use this:
MemoryStream ms = (MemoryStream)dataObject.GetData("FileContents", fileIndex);
Instead of this:
MemoryStream ms = (MemoryStream)dataObject.GetData("FileContents", true);
So it parses every files.
EDIT:
Actually, it doesn't work neither unless program is compiled in Debug rather than Release... It will only work in Debug for some reason

StreamWriter file in use by another process - Writing to fast too frequently?

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.

Display Output in a text file

I have taken the input code through file and i have to generate data according to it and output it's result in a text file as well..
My Output Code is below..
public void Generator()
{
/// ....... Code
public void DisplayTOKENS()
{
using (StreamWriter writer =
new StreamWriter("C:\\Users\\saeed\\Documents\\Outputt.txt"))
{
for (int i = 0; i < j;i++ )
{
tok[i].Display_Token();
} }
}
// and in other structur named TOKEN
public void Display_Token()
{ /*
using (StreamWriter writer =
new StreamWriter("C:\\Users\\saeed\\Documents\\Outputt.txt"))
{
writer.Write("( " + this.Class_Part + " , ");
writer.Write(this.Value_Part + " , ");
writer.Write(this.Line_no + " )");
writer.WriteLine();
}*/
Console.Write("( " + this.Class_Part + " , ");
Console.Write(this.Value_Part + " , ");
Console.Write(this.Line_no + " )");
Console.WriteLine();
}
When i try to directly work in Display_Token then it just simply show the last line in file.. i want to display the complete array in the file. waiting for some positive response !!
That StreamWriter constructor overwrites the existing file. So, each token effectively deletes whatever was written earlier then writes its content. That is why you only see the last token's content in the file.
Use the overload with the "append" argument and pass true so that the existing file is not deleted.
You have to check if file exists and than do "append" operation instead of "overwrite".
// in DisplayTOKENS()
string fileName = "C:\\Users\\saeed\\Documents\\Outputt.txt";
if (System.IO.File.Exists(fileName))
System.IO.File.Delete(fileName);
for (int i = 0; i < j; i++)
{
tok[i].Display_Token(fileName);
}
// in Display_Token(string fileName)
System.IO.File.AppendAllText(fileName, "( " + this.Class_Part + " , " + this.Value_Part + " , " + this.Line_no + " )");

Not able to write a Text on txt File using C#

I have tried to write a string on text file,but its not writing anything and there is no exceptions. My code is:
public void CreateLog(string sLogInfo)
{
string sDestionation = null;
string sFileName = DateTime.Now.ToString("yyyyMMdd") + "_log.txt";
sDestionation = #"D:\Log\";
//sDestionation = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + ConfigurationManager.AppSettings["DestinationPath"].ToString();
string sFile = sDestionation + sFileName;
if (!System.IO.Directory.Exists(sDestionation))
{
System.IO.Directory.CreateDirectory(sDestionation);
}
StreamWriter oWriter = null;
if (!System.IO.File.Exists(sFile))
{
oWriter = File.CreateText(sFile);
}
else
{
oWriter = File.AppendText(sFile);
}
oWriter.WriteLine(DateTime.Now.ToString() + ": " + sLogInfo.Trim());
}
StreamWriter is IDisposable object. You should dispose it after using. For this you can use using statement like this:
public void CreateLog(string sLogInfo)
{
string sDestionation = null;
string sFileName = DateTime.Now.ToString("yyyyMMdd") + "_log.txt";
sDestionation = #"D:\Log\";
var sFile = sDestionation + sFileName;
if (!Directory.Exists(sDestionation))
{
Directory.CreateDirectory(sDestionation);
}
using (var oWriter = new StreamWriter(sFile, true))
oWriter.WriteLine(DateTime.Now + ": " + sLogInfo.Trim());
}
Use File.AppendAllText that will do all the steps (except creating folder) for you.
Otherwise you should properly dispose writer when you are done, preferably with using in the same function:
using(oWriter)
{
oWriter.WriteLine(DateTime.Now.ToString() + ": " + sLogInfo.Trim());
}
Your code looks fine, however, I think you should add at the end of it the following:
oWriter.Close()
You should flush (disposing is enough) your data into the file at the end of your code:
oWriter.Flush(); //Save (Clears all buffers for the current writer and causes any buffered data to be written to the underlying stream.)
oWriter.Dispose(); //Then free this resource
As Yuval mentioned looking at C#'s StreamWriter.cs class it does indeed calls the Flush method internally. See here: Reference

C# save to multiple lines in a text file

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.

Categories

Resources