System.IO.IOException creating File - c#

I have an Error if I write something in a newly created File.
This is my code:
private void ButtonClick(object sender, EventArgs e)
{
Button b = (Button)sender;
string inputKey = b.Text;
for (int i = 0; i < tunes.Length; i++)
{
if (b.Text == tun[i].TuneName)
{
Console.Beep(tun[i].Frequency, 200);
Input.Items.Add(b.Text);
Output.Items.Add(tun[i].TuneName);
if (startButtonPressed == true)
{
filename2 = musicFileName + ".csv";
File.WriteAllText(filename2, tun[i].TuneName);
RecordList.Items.Add(tun[i].TuneName);
}
}
}
}
The Error comes at Line : File.WriteAllText()...
It says that the File can not be used, because it's used by an another process,but I havent opened any File.

I'd use a Filestream generated by File.Create(), but I'd make the loop inside the using statement, so you ensure that all ressources will be released at the end (that's why you use using).
using (FileStream fs = File.Create(Path.Combine(musicFileName, ".csv")))
{
foreach (tun in tunes)
{
fs.Write(tun.TuneName);
}
}
The problem you were actually having is, that you were never closing your file. You should look up using-keyword. It can used only with classes implementing the IDisponsable Interface. It then will call disponse() at the end of the using block and all ressources will be released, eg the file will be closed.

You need to make sure that the variable filename2 contains a valid path like C:\temp\myfile and not just myfile additionally you might need to run visual studio with elevated privilege if the location is not accessible otherwise.

You could also use streamwriter...
using (StreamWriter writer =new StreamWriter(musicFileName + ".csv";))
{
writer.Write(tun[i].TuneName);
}

Related

Save and delete Excel file saved using HttpPostedFileBase

I am uploading an Excel file and extracting data from that and saving it into a database. I am using MVC4 .NET Framework. This is my code from class:
public static void Upload(HttpPostedFileBase File)
{
NIKEntities1 obj = new NIKEntities1();
MyApp = new Excel.Application();
MyApp.Visible = false;
string extension = System.IO.Path.GetExtension(File.FileName);
string pic = "Excel" + extension;
string path = System.IO.Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/Excel"), pic);
File.SaveAs(path);
MyBook = MyApp.Workbooks.Open(path);
MySheet = (Excel.Worksheet)MyBook.Sheets[1]; // Explicit cast is not required here
int lastRow = MySheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell).Row;
List<Employee> EmpList = new List<Employee>();
for (int index = 2; index <= lastRow; index++)
{
System.Array MyValues = (System.Array)MySheet.get_Range("A" +
index.ToString(), "B" + index.ToString()).Cells.Value;
EmpList.Add(new Employee
{
BatchID = MyValues.GetValue(1, 1).ToString(),
BatchName = MyValues.GetValue(1, 2).ToString()
});
}
for (int i = 0; i < EmpList.Count; i++)
{
int x=obj.USP_InsertBatches(EmpList[i].BatchID, EmpList[i].BatchName);
}
}
}
class Employee
{
public string BatchID;
public string BatchName;
}
This code is working perfectly the first time but next time it says that file is currently in use. So I thought of deleting the file at the end of code using the following line:
File.Delete(path);
But this line threw error:
HttpPostedFileBase does not contain definition for Delete
Also, if I don't write this line and try to execute code again it says that it can't save because a file exists with same name and could not be replaced because it is currently in use.
What should I do to get rid of this:
(File.Delete()) Error
Any other way of accessing the Excel file which I am receiving without saving will also be very helpful because I have to just access the data one time.
The File you use there is your variable that is the input parameter of your method. That parameter is of type HttpPostedFileBase and that type has no instance methods (nor static ones for that matter) that allow you to delete that File instance.
You are probably looking for the static Delete method on the File type that is in the System.IO namespace.
A quickfix would be to be explicit about which File you mean:
System.IO.File.Delete(path);
You might want to consider a different naming guideline for your variables though. In c# we tend to write variables starting with a lower case letter. Almost all types in the framework start with an Uppercase letter. Which makes it easier to distinguish the thing file and the type File.
Do notice that a file can only be deleted if it is closed by all processes and all file handles are cleared by the filesystem. In your case you have to make sure Excel closed the file and released it's handles. If you have the search indexer running or a rough virus scanner you might have to try a few times before giving up.
I normally use this code:
// make sure here all Ole Automation servers (like Excel or Word)
// have closed the file (so close the workbook, document etc)
// we iterate a couple of times (10 in this case)
for(int i=0; i< 10; i++)
{
try
{
System.IO.File.Delete(path);
break;
} catch (Exception exc)
{
Trace.WriteLine("failed delete {0}", exc.Message);
// let other threads do some work first
// http://blogs.msmvps.com/peterritchie/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program/
Thread.Sleep(0);
}
}
From what I can tell, you are opening Excel, reading the file but never closing the Excel.
Add:
MyApp.Workbooks.Close();
MyApp.Quit();
at the end of the Upload function. Even better, wrap whole code you got in
try{
//here goes your current code
}
catch(Exception e)
{
//manage exception
}
finally
{
MyApp.Workbooks.Close();
MyApp.Quit();
}
You initialize MyApp outside try catch block, then whatever happens close the file.

Delete a file which is used by another process in c#

I am trying to delete one file which was used by certain another process of my Application.
So its giving an Error that file is used by certain another process.
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
DirectoryInfo NewDir = new DirectoryInfo(imagefolderpath1);
FileInfo[] files = NewDir.GetFiles("*.jpg");
foreach (var item in files)
{
string strFile = imagefolderpath1 + "\\" + item.ToString();
if (File.Exists(strFile))
{
File.Delete(strFile);
}
}
}
How should i solve this problem can you please help me????
You need to kill the process which is causing this issue by the following code, something like :
string fileName = #"D:\pathname.jpg";//Path to locked file
Process Handletool = new Process();
Handletool.StartInfo.FileName = "handle.exe";
Handletool.StartInfo.Arguments = fileName+" /accepteula";
Handletool.StartInfo.UseShellExecute = false;
Handletool.StartInfo.RedirectStandardOutput = true;
Handletool.Start();
Handletool.WaitForExit();
string outputTool = Handletool.StandardOutput.ReadToEnd();
string matchPattern = #"(?<=\s+pid:\s+)\b(\d+)\b(?=\s+)";
foreach(Match match in Regex.Matches(outputTool, matchPattern))
{
Process.GetProcessById(int.Parse(match.Value)).Kill();
}
u can get Handle.exe from http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx
The file needs to be released by the other program before it can be deleted. You can use Process Explorer to find out what is locking it if you don't know.
you can't access the file used by another process. But if it's not critical for you app to do this later, you can do this in the System.AppDomain.ProcessExit event handler.
just add the file to a centrally managed list and register your cleanup routine like here:
AppDomain.CurrentDomain.ProcessExit += new EventHandler(deleteFilesIfPossibleNow);
in the handler you must still handle exceptions if files are still accessed from another processes.
instead of using _FormClosed you might want to try launching the form from your other code like this:
DirectoryInfo NewDir;
FileInfo[] files;
using (var form = new Form1())
{
var result = form.ShowDialog();
if (result == DialogResult.Close)
{
NewDir = new DirectoryInfo(imagefolderpath1);
files = NewDir.GetFiles("*.jpg");
}
}
foreach(var item in files) {
string strFile = imagefolderpath1 + "\\" + item.toString();
File.Delete(strFile);
}
i wasn't a hundred % sure how your program is meant to work but you can grab information from the forms before they close then close the files they were using after with this kind of method

C# ArgumentOutOfRangeException when trying to retrieve data from a struct within an arraylist

Will try to post only relevant code as my program is quite large already. Basically the program adds customer information into an arraylist-struct. I've got the storing and saving and file loading working flawlessly, but when I'm trying to show the data I'm getting exceptions.
Most of the main code is on a class seperate to the forms, and this particular call comes from "frmViewRecords".
public void ViewData(int currentRecord)
{
string fn = ((custDetails)datalist[currentRecord]).firstName;
frmViewRecords viewRecords = new frmViewRecords();
viewRecords.WriteData(fn);
}
The above code is what causes the exception, but the code for the messagebox below works fine.
public void LoadData()
{
bool fileLoaded = false;
//Load the database
try
{
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read); //Create the filestream
try
{
BinaryFormatter bf = new BinaryFormatter(); //New binary formatter for deserialization
datalist = (ArrayList)bf.Deserialize(fs);
fileLoaded = true; //Update the fileLoaded bool so that it doesn't open the file dialog instance
recordCount = datalist.Count;
MessageBox.Show("" + filename + " loaded successfully."); //Inform the user that the file was automatically loaded
MessageBox.Show("Test: " + ((custDetails)datalist[0]).firstName);
}
catch
{
MessageBox.Show("Could not de-serialise from " + filename, "FILE LOADING PROBLEM", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
fs.Close();
}
catch
{
if (MessageBox.Show("File isn't in the right location, this is normal if a dataset does not yet exist.\n\n If the file exists elsewhere click no and you will be prompted to find the database file, else click yes to create a default file.", "FILE LOADING PROBLEM", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
{
fileLoaded = true;
CreateDefaultData();
}
}
I have tried 'string fn = ((custDetails)datalist[0]).firstName;' to ensure it isn't the variable causing the problems, and the exception still happens. I am pretty much out of ideas. The problem cannot be with struct or arraylist definition as the the messagebox in LoadData() works fine and outputs the correct information. I tried moving the messagebox to the ViewData method and that also began giving an exception so I can only assume something is wrong with my method?
These methods are on "MainClass.cs" and below is how I called the method from frmViewRecords:
MainClass mainClass = new MainClass();
int currentRecord = 0;
private void LoadData()
{
mainClass.ViewData(currentRecord);
}
It might be worth mentioning that previously, I was calling the data straight from frmViewRecords like so:
txtFirstName.Text = ((MainClass.custDetails)mainClass.datalist[currentRecord].firstName;
But after getting the same exception while the messagebox prompt worked, I rewrote it to the above and still I get the problem so I have no idea what is causing it.
There are no items in the datalist. Probably the value of the recordCount in the LoadData is zero as well. Try this:
if(datalist.Count != 0) { /* Get the current record */ }

Creating FileInfo - Unexpected Behavior

I am trying to create a file with a FileInfo object and I am getting strange behavior.
Here is the gist of what I am doing -
public void CreateLog()
{
FileInfo LogFile = new FileInfo("");
if (!LogFile.Directory.Exists) { LogFile.Directory.Create(); }
if (!LogFile.Exists) { LogFile.Create(); }
if (LogFile.Length == 0)
{
using (StreamWriter Writer = LogFile.AppendText())
{
Writer.WriteLine("Quotes for " + Instrument.InstrumentID);
Writer.WriteLine("Time,Bid Size,Bid Price,Ask Price,Ask Size");
}
}
}
However, when it checks to see the length of the logfile, it says that the file does not exist (I checked - it does exist).
When I substitute LogFile.Length with the following:
File.ReadAllLines(LogFile.FullName).Length;
Then I get an exception that says that it cannot access the file because something else is already accessing it.
BUT, if I do a Thread.Sleep(500) before I do ReadAllLines, then it seems to work fine.
What am I missing?
LogFile.Create() if you user this function ,you may lock the file, so you can use using ,like this
using(LogFile.Create()){}
after that you can use the file again

Writing to a text file on form closing event

I am trying to write some strings to a text file on the formclosing event. The problem is that the streamwriter doesn't write anything, it just writes a blank slate. I have 2 different text files, the first one will log all of the graph data and the second text file will log a couple of preferences relevant to my application. My code is shown below for both the closing event and a seperate workhorse method:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason.Equals(CloseReason.WindowsShutDown) || (e.CloseReason.Equals(CloseReason.UserClosing)))
{
if (MessageBox.Show("You are closing this application.\n\nAre you sure you wish to exit ?", "Warning: Not Submitted", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Stop) == DialogResult.Yes)
{
writeContents("Interrupted");
return;
}
else
e.Cancel = true;
}
}
private void writeContents(string status)
{
//---writes the graph data-----
TextWriter twBackupData = new StreamWriter("C://springTestBackupData.txt");
twBackupData.WriteLine("--Cycle#-- --TorqueLower-- --TorqueUpper--");
//writes the table of values in there, assume x and y are the same size arrays
for(int i = 0; i < x.Count; i++)
{
twBackupData.WriteLine(x[i] + " " + y_lower[i] + " " + y_upper[i]);
}
//---writes some of the preferences------
TextWriter twBackupDataInfo = new StreamWriter("C://springTestBackupInfo.txt");
twBackupDataInfo.WriteLine(status);
twBackupDataInfo.WriteLine(cycleCount.ToString());
twBackupDataInfo.WriteLine(section.ToString());
twBackupDataInfo.WriteLine(revsPerCycle.ToString());
twBackupDataInfo.WriteLine(preturns.ToString());
twBackupDataInfo.WriteLine(direction.ToString());
}
If you can provide advice or help me find out why it's writing blanks I would greatly appreciate it. Thank you!
You need to close the StreamWriter using the using statement.
It's much easier to just use:
var linesToWrite = new list<string>();
linesToWrite.Add(status);
linesToWrite.Add(cycleCount.ToString());
...
File.WriteAllLines("C://springTestBackupData.txt", linesToWrite);
You need to close/dispose the writer for it to write, otherwise it never flushes its stream (i.e. writes the data to the file)
Using the 'using' statement automatically disposes of an object when it goes out of scope so:
using(TextWriter twBackupData = new StreamWriter("C://springTestBackupData.txt"))
{
// Do your stuff here - write to the tw ---
twBackupData.WriteLine("--Cycle#-- --TorqueLower-- --TorqueUpper--");
//writes the table of values in there, assume x and y are the same size arrays
for(int i = 0; i < x.Count; i++)
{
twBackupData.WriteLine(x[i] + " " + y_lower[i] + " " + y_upper[i]);
}
}
Will ensure your file gets written to
More info here:
http://msdn.microsoft.com/en-us/library/yh598w02.aspx
You need to do .Close() on your StreamWriters;

Categories

Resources